这道题,其实思路很简单,但是。。坑是很多的
思路
我们发现L,R很大,但是区间只有1e6。
我们知道,R必定包含一个不超过根号R的质因子,所以只需要用筛法求出2~根号R的所有质数,对于每个质数p,把[L,R]中能被p整除的数标记,即标记i*p为合数,最终[L,R]中没被标记的就是质数,一个一个挨着比较就好
#include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <iostream> #include <algorithm> #define N 700003 #define LL long long #define INF 2100000000 using namespace std; int not_prime[N],he[1000050]; int prime[N]; int tot=0; void work(int n) { for(LL i=2;i<=n;++i) { if(!not_prime[i]) prime[++tot]=i; for(LL j=1;j<=tot&&prime[j]*i<=n;++j) { not_prime[prime[j]*i]=1; if(i%prime[j]==0)break; } } } int main() { LL l,r; work(50000); while(scanf("%lld%lld",&l,&r)!=EOF) { if(l==1)l=2; memset(he,0,sizeof(he)); for(int i=1;i<=tot;++i) { if(prime[i]*prime[i]>r) break; int a=l/prime[i]; a=max(2,a); int b=r/prime[i]; for(int j=a;j<=b;++j) if(j*prime[i]-l>=0)he[j*prime[i]-l]=1; } LL front=-INF,minn=INF,maxx=-INF; int ansmax1=0,ansmax2=0,ansmin1=0,ansmin2=0; for(LL i=l;i<=r;++i)//用long long,不然会RE!!! { if(he[i-l])continue; if(front==-INF){front=i;continue;} else { if(i-front<minn)ansmin1=front,ansmin2=i,minn=i-front; if(i-front>maxx)ansmax1=front,ansmax2=i,maxx=i-front; front=i; } } if(ansmax2==0)printf("There are no adjacent primes. "); else printf("%d,%d are closest, %d,%d are most distant. ",ansmin1,ansmin2,ansmax1,ansmax2); } return 0; }
然后这道题卡了我很久。。真的卡了我很久,不是TLE就是RE。
有两个很大的坑点可能只对于我来说吧
1.RE:L到R的范围是2^31,很容易爆int
如果在最后的循环里这样写
for(int i=l;i<=r;++i)
就RE。。。
所以应该用LL
2.TLE
我原来筛[L,R]间的合数是这样写的
for(int i=1;i<=tot;++i) { if(prime[i]*prime[i]>r) break; int j=l/prime[i]; if(j<2)j=2; for(;j*prime[i]<=r;++j) if(j*prime[i]-l>=0)he[j*prime[i]-l]=1; }
然后应该这么写
for(int i=1;i<=tot;++i) { if(prime[i]*prime[i]>r) break; int a=l/prime[i]; a=max(2,a); int b=r/prime[i]; for(int j=a;j<=b;++j) if(j*prime[i]-l>=0)he[j*prime[i]-l]=1; }
把prime[i]*j放在循环中会TLE。。(污秽之语)
这道题,真的说不出话。。