版权声明:虽然我只是个小蒟蒻但转载也请注明出处哦 https://blog.csdn.net/weixin_42557561/article/details/82316772
大致题意
给定 L, R,保证 L, R在int范围以内, R − L ≤ 10^6 ,问 [L, R] 中距离最近的两个相邻质数,和距离最远的两个相邻质数。区间内若没有相邻的质数则输出:There are no adjacent primes.
分析
这个范围告诉我们任何一种我们熟知的求素数的方法都会TLE(except Miller_Rabin),那我们就来两次素数筛
先筛出以内的所有素数,然后再用这些素数去筛 L 到 R 这个区间的素数,就搞定啦
不过这道题有个坑点,一不小心就会RE,我就这样卡死了,不过在dzy的帮助下还是解决了,%%%%感谢DZYO大佬的帮助%%%%
先来组数据,大家感受一下:2146483648 2147483647
等会儿我会在程序中指出问题所在
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include <assert.h>
#define N 50000
using namespace std;
int l,r,pri[N+10],num=0,p[1000009],hh[1000009];
bool mark[N+10];
void prime(){//我用的是线性筛,进行第一次筛
mark[1]=1;
for(int i=2;i<=N;++i){
if(!mark[i]) pri[++num]=i;
for(int j=1;j<=num&&pri[j]*i<=N;++j){
mark[pri[j]*i]=1;
if(i%pri[j]==0) break;
}
}
}
int main(){
prime();
while(scanf("%d%d",&l,&r)!=EOF){
memset(p,0,sizeof(p));//每次都要清空
if(l==1) l=2;//反正1也没用,而且会干扰后面的答案,所以我们直接忽略
int i,j,k=sqrt(r)+1;
for(i=2;i<=k;++i){
if(!mark[i]){
int down=l/i;
if(down<=1) down=2;
for(j=down;1ll*j*i<=r;++j) p[1ll*j*i-l]=1;
}
}
int tot=0,minn=(1ll<<31)-1,a1,a2,maxn=-1,b1,b2;
for(long long i=l;i<=r;++i) if(!p[i-l]) hh[++tot]=i;//就是这个地方,如果r恰好取到int的最大值时,再i++一次,i就爆了;
if(tot<=1) printf("There are no adjacent primes.\n");
else{
for(i=2;i<=tot;++i){
int dis=hh[i]-hh[i-1];
if(dis<minn){minn=dis;a1=hh[i-1];a2=hh[i];}
if(dis>maxn){maxn=dis;b1=hh[i-1];b2=hh[i];}
}
printf("%d,%d are closest, %d,%d are most distant.\n",a1,a2,b1,b2);
}
}
return 0;
}
最后来一句:
如果有多组数据的,一定要考虑清空,初始化