这道题用到二次筛选素数的方法,优化了时间复杂度,不然会超时;区间长度在10^6以内,可用数组标记,再大也不怎么能实现。
这道题是限制多多的。
题目出现的主要问题 1、TLE 2、RE
主要说说RE的问题:
1、用数组标记L--U的素数时,容易超下界,但是我当时写的代码没什么问题,可证明一定不会超
2、这个就是个奇葩了
LL s=(LL)sqrt(U+0.0); for(LL i=0;prim[i] <= s;i++)//关键是s的设定 for(LL i=0;prim[i]*prim[i]<=U;i++)//原来写的是这个,果断被坑了 //后来通过强制转换都不能解决这个问题,一直RE
3、另一个会出错的例子
for(int i=1;i<=n;i++) for(int j=1;j!=i; j++) //但是这个就是思路的问题了,因为for循环里的是跳出判断条件,这个很容易错啊
4、总结上面的两个问题,以后统一在for循环里面写continue或者是break
AC的代码:
#include<iostream> #include<string.h> #include<stdio.h> #include<math.h> #define LL long long #define maxn 46600 bool flag[maxn]; int prim[maxn/3+5]; bool f[1000000+5]; LL cnt; using namespace std; void built() { cnt=0; memset(flag,0,sizeof(flag)); for(int i=2;i<=maxn;i++) { if(!flag[i]) prim[cnt++]=i; for(int j=0; j<cnt && prim[j]*i<=maxn;j++) { flag[i*prim[j]]=1; if (i%prim[j]==0) break; } } return; } void builtf(LL L,LL U) { memset(f,0,sizeof(f)); LL s=(LL)sqrt(U+0.0); if ( L == 1 ) f[0]=1; for(LL i=0;prim[i] <= s;i++) { int sj; int p=prim[i]; if ( p >= L) sj=2; else { if ( L % p == 0) sj=L/p; else sj=L/p+1; } for(LL j=sj;j*p<=U;j++) f[j*p-L]=1;//合数是1 } } int main() { LL L,U; built(); while(~scanf("%I64d%I64d",&L,&U)) { builtf(L,U); LL min1,min2,max1,max2; int t=0; for(LL i=0;i<=U-L;i++) { if ( t==0 && !f[i] ) {min1=i,t++;continue;} if ( t==1 && !f[i] ) {min2=i,t++;break;} } if (t<2) printf("There are no adjacent primes. "); else { LL dis1=min2-min1; LL dis2=dis1; LL last=min2; max1=min1;max2=min2; for(LL i=min2+1;i<=U-L;i++) { if (!f[i]) { if(i-last<dis1) { min1=last; min2=i; dis1=min2-min1; } if (i-last>dis2) { max1=last; max2=i; dis2=max2-max1; } last=i; } } printf("%I64d,%I64d are closest, %I64d,%I64d are most distant. ",min1+L,min2+L,max1+L,max2+L); } } return 0; }