POJ2689 Eratothenes质数筛
Waterloo October 1998
https://vjudge.net/problem/POJ-2689
通过某种方式到waterloo的官网(http://acm.student.cs.uwaterloo.ca/~acm00/98oct17/solutions/)上找到了测试数据:
//data.in
1 100
1000000000 1001000000
1000000000 1000000008
2147483587 2147483647
2147481000 2147483646
1 2
2 3
//data.out
2,3 are closest, 89,97 are most distant.
1000000007,1000000009 are closest, 1000097621,1000097797 are most distant.
There are no adjacent primes.
2147483629,2147483647 are closest, 2147483587,2147483629 are most distant.
2147481899,2147481901 are closest, 2147481673,2147481793 are most distant.
There are no adjacent primes.
2,3 are closest, 2,3 are most distant.
题目大意
给出左右边界l,r(1<=l<r<=2<<31),r-l<=1e6,问其中相邻的质数最近的是哪两个,最远的是哪两个
,如果期间没有相邻质数就输出没有
解法
2<<31是肯定不可能直接筛的,但是因为任意i>=2的合数都存在j<=sqrt(i),使得j整除i,那就用Eratothenes筛一下sqrt(2<<31)(46000多,所以开了47000)以下的质数i,然后在从ceiling(l/i)到floor(r/i)依次乘因子i(又有点像Eratothenes)从而标记l,r之间的合数,从而筛出质数,然后遍历即可
注意事项
1)数组要开大一点(1e6+1000),否则会RE,多开个一千分之一没什么大不了的
2)注意1不是质数,所以需要特判,直接改成从2开始判(这思路真的想不到)
复习反省
1)忘了质数的倍数>=2的时候才能筛掉
2)忘了1特判(真香!)
3)不知道为什么eratothenes第一次写成了筛到
n
\sqrt{n}
n就停了
AC代码
Time 125ms Memory 4604 KB length 1920 Lang G++
注意这里的used两次筛素数都用了
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn = 1e6+1000;
const int maxm = 47000;
int used[maxn];
int prime[maxm];
int num = 0;
void eratothses()
{
memset(used,0,sizeof(used));
for(int i = 2; i <=maxm; i++)
{
if(used[i])
{
continue;
}
else
{
prime[num++] = i;
for(int j = 2; j<maxn/i; j++)
used[i*j] = 1;
}
}
}
int main()
{
int l,r;
eratothses();
while(cin >> l >> r)
{
for(int i = 0;i <r-l+1;i++)used[i] = 0;
if(l == 1)l = 2;
for(int i = 0; prime[i]<sqrt(r); i++)
{
int tmp = prime[i];
for(int j = l/tmp; j <=r/tmp; j++)
{
if(tmp*j>=l&&tmp*j<=r&&j>=2)
used[tmp*j-l] = 1;
}
}
int ans1 = maxn,ans2 = -1;
int pre = -1;
int a,b,c,d;
int nu = 0;
for(int i = 0; i <r-l+1; i++)
{
if(!used[i])
{
if(nu == 0)
{
nu++;
pre = i;
}
else
{
if(i-pre < ans1)
{
ans1 = i-pre;
a = pre;
b = i;
}
if(i-pre > ans2)
{
ans2 = i-pre;
c = pre;
d = i;
}
pre = i;nu++;
}
}
}
if(nu <= 1)
{
cout << "There are no adjacent primes."<<endl;
}
else
{
cout << a+l<<','<<b+l<<" are closest, "<<c+l<<','<<d+l<<" are most distant."<<endl;
}
}
return 0;
}