分析:因为题目的数据范围是小于2的31次方-1,而最快的线性筛,时间复杂度也只是O(n)的,显然这样是没用的。
但是,由最早学的判断质数的方法可以看做出,假如一个数n如果是合数,那么n的最小质因子一定是小于根号n 的,那么根号下2.1的10的9次方,最小的质因子一定是在1~50000之间,那么我们就可以先预处理出来1~50000的质数,再找到大于等于L的每一个质因数倍数,然后把L,R之间的所有合数筛掉,最终剩余的就只是质数。再遍历处理出来的质数,就可以得到答案。
注意:找到质因子的倍数,最小得是质因子得两倍
求一个大于等于这个数的倍数的方法:x=(l+p-1)/p*p(其实这里就是上取整);这个式子的意义是先求出来l是p的多少倍,假如l不能整除p那么就是(l/p)+1,反之,就是l/p
代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
int prime[N];
bool st[N];
int cnt;
void init(int x)
{
memset(st,0,sizeof st);
cnt=0;
for(int i=2;i<=x;i++)
{
if(!st[i]) prime[cnt++]=i;
for(int j=0;prime[j]<=x/i;j++)
{
st[i*prime[j]]=true;
if(i%prime[j]==0) break;
}
}
}
int main()
{
int l,r;
while(cin>>l>>r)
{
init(50000);
memset(st,0,sizeof st);
for(int i=0;i<cnt;i++)
{
LL p=prime[i];
for(LL j=max(p*2,(l+p-1)/p*p); j<=r;j+=p)
st[j-l]=true;//先用偏移量,后边会再加上,偏移量一定不会超过10^6
}
cnt=0;
for(int i=0;i<=r-l;i++)
{
if(!st[i] && i+l>=2) prime[cnt++] =i+l;
}
// cout<<cnt<<endl;
if(cnt<2) puts("There are no adjacent primes.");
else
{
int minp=0,maxp=0;
for(int i=0;i+1<cnt;i++)
{
int d=prime[i+1]-prime[i];
if(d < prime[minp+1]-prime[minp]) minp=i;
if(d > prime[maxp+1]-prime[maxp]) maxp=i;
}
printf("%d,%d are closest, %d,%d are most distant.\n",
prime[minp],prime[minp+1],
prime[maxp],prime[maxp+1]);
}
}
return 0;
}