POJ 2689 Prime Distance (经典素数筛选)

转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents           by---cxlove

POJ 2689 Prime Distance 

http://poj.org/problem?id=2689

区间范围很大,2^31左右,不可能筛选出所有素数,时间和空间都不允许。

但是可以发现询问的区间不是很大,相关是在10^6,这就是本题的突破口了。

首先做一次素数筛选,筛选出sqrt(区间上界)的素数,然后用这些,对询问区间进行筛选,空间也只需要10^6。

注意中间会溢出int

  1. #include<iostream>  
  2. #include<cstring>  
  3. #include<queue>  
  4. #include<cstdio>  
  5. #include<cmath>  
  6. #include<algorithm>  
  7. #define N 100005  
  8. #define inf  1<<30  
  9. #define MOD 9973  
  10. #define LL long long  
  11. #define eps 1e-7  
  12. #define zero(a) fabs(a)<eps  
  13. #define equal(a,b) zero(a-b)  
  14. using namespace std;  
  15. bool flag[100005];  
  16. int prime[100005],cnt=0;  
  17. //先打出sqrt(上界)的素数表  
  18. void Prime(){  
  19.     for(int i=2;i<=47000;i++){  
  20.         if(flag[i])  
  21.             continue;  
  22.         prime[cnt++]=i;  
  23.         for(int j=2;j*i<=47000;j++)  
  24.             flag[i*j]=true;  
  25.     }  
  26. }  
  27. bool isprime[1000005];  
  28. int a[1000005],c;  
  29. int main(){  
  30.     int l,r;  
  31.     Prime();  
  32.     while(scanf("%d%d",&l,&r)!=EOF){  
  33.         memset(isprime,true,sizeof(isprime));  
  34.         if(l==1) l=2;  
  35.         //利用之前的素数,进行二次筛选,注意防溢出  
  36.         for(int i=0;i<cnt&&(LL)prime[i]*prime[i]<=r;i++){  
  37.             int s=l/prime[i]+(l%prime[i]>0);  
  38.             if(s==1)  
  39.                 s=2;  
  40.             //不能从1开始,不然就把素数给判成合数了  
  41.             for(int j=s;(LL)j*prime[i]<=r;j++)  
  42.                 if((LL)j*prime[i]>=l)  
  43.                     isprime[j*prime[i]-l]=false;  
  44.         }  
  45.         c=0;  
  46.         for(int i=0;i<=r-l;i++)  
  47.             if(isprime[i])  
  48.                 a[c++]=i+l;  
  49.         //少于两个素数  
  50.         if(c<2){  
  51.             puts("There are no adjacent primes.");  
  52.             continue;  
  53.         }  
  54.         int x1=0,x2=0,y1=0,y2=inf;  
  55.         for(int i=1;i<c;i++){  
  56.             if(a[i]-a[i-1]>x2-x1){  
  57.                 x1=a[i-1];  
  58.                 x2=a[i];  
  59.             }  
  60.             if(a[i]-a[i-1]<y2-y1){  
  61.                 y1=a[i-1];  
  62.                 y2=a[i];  
  63.             }  
  64.         }  
  65.         printf("%d,%d are closest, %d,%d are most distant.\n",y1,y2,x1,x2);  
  66.     }  
  67.     return 0;  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值