原题见洛谷。
首先一次预处理出根号R内的所有质数。虽然L,R很大但是它们相差不大,对于每个筛出来的质数,把[L,R]内所有能被它整除的数标记,然后剩下的数从L到R扫一遍就可以统计答案了。注意标记时的细节。
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAXN=46500;
int vis[1000005],tot=0;
LL prime[MAXN];
void pre()
{
for(LL i=2;i<=46500;i++)
{
if(!vis[i]) prime[++tot]=i;
for(LL j=1;j<=tot&&prime[j]*i<=46500;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
}
int main()
{
pre();
LL L,R;
while(scanf("%lld%lld",&L,&R)==2)
{
memset(vis,0,sizeof(vis));
for(LL i=1;i<=tot&&prime[i]<=R;i++)
{
for(LL j=L/prime[i];j<=R/prime[i];j++)
if(j>1&&j*prime[i]>=L) vis[j*prime[i]-L]=1;
}
if(L==1) vis[0]=1;
LL dis1=R-L+1,dis2=0,lastp=-1,x1,y1,x2,y2;
for(int i=0;i<=R-L;i++)
{
if(!vis[i])
{
if(lastp>=0)
{
if(i-lastp<dis1)
{
dis1=i-lastp;
x1=lastp; y1=i;
}
if(i-lastp>dis2)
{
dis2=i-lastp;
x2=lastp; y2=i;
}
}
lastp=i;
}
}
if(!dis2) puts("There are no adjacent primes.");
else cout<<x1+L<<','<<y1+L<<" are closest, "<<x2+L<<','<<y2+L<<" are most distant.\n";
}
return 0;
}