题意:给你一个闭区间[a,b],求一个最小的L,使得在区间[a,b-L+1]内任取一个数x,可以满足在x,x+1,x+2,……,x+L-2,x+L-1内至少包含k个素数。(1<=a,b,k<=10^6)
•
•考察内容:筛素数、二分
•
•一边筛素数,一边处理出一个前缀和sum
•sum(i)表示[1,i]中有多少素数
•那么我们每次查询区间[l,r]中有多少素数,直接查sum[r]-sum[l-1]就可以了
•接下去我们按照题意,对答案L进行二分就可以了
这是陶叔的解释
我的解释全在注释里头了
#include<iostream> using namespace std; int a,b,k; int sum[1000010];//默认的值为0 int pri[1000010];//筛选后的素数保存在此数组中 //筛选1-b的素数 void init() { for(int i = 2;i < 1000010;i++) { sum[i] = sum[i-1]; if(pri[i])//如果不是素数就跳过 { continue; } sum[i]++;//否则就在前一个的基础上++ for(int j =i + i;j < 1000010;j+= i)//把所有为i倍数的标记为1,代表非素数 { pri[j] = 1; } } } //检测这个mid值是否满足条件 bool check(int mid) { for(int i = a;i <= b - mid +1;i++) { if(sum[i+mid - 1] - sum[i -1] < k)//判断i到i+mid中是否素数至少为k个 { return 0; } } return 1; } int main() { init(); cin >> a >> b >> k; //若整个区间的素数少于k个,直接输出-1结束 if(sum[b] - sum[a -1] < k) { cout << "-1" << endl; return 0; } //采用二分法找L int l = 1,r = b - a +1,ans; while(l <= r) { int mid = (l + r) >> 1; if(check(mid)) { ans = mid; r = mid-1; } else { l = mid + 1; } } cout << ans << endl; return 0; }
重点还是要培养二分的意识