今天写个大区间素数筛
POJ3689
给你一个区间[l, r],1 <= l <= r <= 1e9, r - l < 1e6,求区间内相邻的素数差值最大值和最小值
显然直接筛是不太现实的,注意到区间只有1e6。
思路转换为把[l, r]的合数求出来,剩下的就是素数直接枚举就行了。
如何求出区间中的合数?
首先知道最小的质因子是sqrt(int) = 2 ^ 16,所以先求出小于2 ^ 16的所有素数。则区间[l,u]中的合数,必定可以表示为这些素数的倍数,然后直接在这个区间枚举就行了。
另外就是需要平移一下[l, r],因为开不了1e9的数组嘛。
int prime[maxn], f[maxn];
bool vis[maxn];
int l, r;
int t;
void init(){
memset(vis, 0, sizeof vis);
int m = sqrt(1e6);
rep(i, 2, m){
if(!vis[i]){
for(int j = i * i; j < maxn; j += i) vis[j] = 1;
}
}
t = 0;
rep(i, 2, maxn - 1) if(!vis[i]) prime[t++] = i;
}
int main()
{
init();
while(~scanf("%d %d", &l, &r)){
if(l == 1) l = 2;
fill(f, f + r - l + 1, 0);
rep(i, 0, t - 1){
int a = (l - 1) / prime[i] + 1, b = r / prime[i];
rep(j, a, b) if(j > 1) f[j*prime[i]-l] = 1;
}
int p = -1, Max = -inf, Min = inf, x1, y1, x2, y2;
rep(i, 0, r - l){
if(f[i] == 0){
if(p == -1) { p = i; continue; }
if(Max < i - p) Max = i - p, x1 = p + l, y1 = i + l;
if(Min > i - p) Min = i - p, x2 = p + l, y2 = i + l;
p = i;
}
}
if(Max == -inf) puts("There are no adjacent primes.");
else printf("%d,%d are closest, %d,%d are most distant.\n", x2, y2, x1, y1);
}
return 0;
}