完全可以用二次筛法来做,虽然我只是一遍就筛出来,第一次,先找出[1,sqrt(INT_MAX+0.5)]间的素数。
第二遍利用第一遍找出的素数找出[L,U]内的素数,映射到一个数组里面,。
具体的处理方法有:开一个数组装下该区间内所有的素数,或者表示某个值是否为素数。
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<climits>
using namespace std;
typedef long long ll;
const int INF =0x3f3f3f3f;
const int maxn=1000000 ;
bool vis[maxn+5];
int nex[maxn+5];
int st,ed;
void pre()
{
memset(vis,0,sizeof vis);
for(ll i=2;i*i<=INT_MAX;i++) if(i<=ed) //
{
ll p=st/i;
ll le=p*i;
if(le<st) le+=i;//这个地方可能会爆int
for(ll j=le;j<=ed;j+=i) if(j!=i)
{
vis[j-st]=1;
}
}
if(st<=1) vis[1-st]=1;
int last=-1;
for(int i=ed-st;i>=0;i--) if(!vis[i])
{
nex[i]=last;
last=i;
}
}
void updatemin(int &ansL,int &ansR ,int le,int ri)
{
if(ansL==-1||ansR-ansL>ri-le)
{
ansL=le+st;
ansR=ri+st;
}
}
void updatemax(int &ansL,int &ansR ,int le,int ri)
{
if(ansL==-1||ansR-ansL<ri-le)
{
ansL=le+st;
ansR=ri+st;
}
}
void work()
{
int i;
for( i=st-st;i<=ed-st;i++) if(!vis[i])
{
break;
}
if(i>ed-st||nex[i]==-1)
{
puts("There are no adjacent primes.");
return;
}
int ansL=-1,ansR=-1;
for(int p=i;~nex[p];p=nex[p])
{
updatemin(ansL,ansR,p,nex[p] );
}
printf("%d,%d are closest, ",ansL,ansR);
ansL=-1,ansR=-1;
for(int p=i;~nex[p];p=nex[p])
{
updatemax(ansL,ansR,p,nex[p] );
}
printf("%d,%d are most distant.\n",ansL,ansR);
}
int main()
{
while(~scanf("%d%d",&st,&ed))
{
pre();
work();
}
return 0;
}