• POJ2689:Prime Distance——题解


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

    题目大意,给不超过int的l,r,其中r-l+1<=1000000,筛出其中的素数,并且求出相邻素数差值最大和最小的一对。

    ——————————————————

    显然这是一道筛出l和r之间素数的裸题。

    我们发现对于区间里的一个合数,其最大质因子不会超过50000(不然50000平方就大于2147483647)

    秉承着正难则反的思想,筛1-50000素数,然后用一种很神奇的方法判断掉区间里的合数,统计素数即可。

    判断方法:

    首先我们将每个素数(记为su)平方得到t,一定是合数。

    如果发现其<l。

    我们就可以t=l/su*su,得到的也一定是合数。

    如果此时仍然<l,我们为t+=su,得到的还是合数。

    当然如果超了r那就continue;

    然后对于t打标记。

    然后不断地t+=su直到超r为止。

    可以发现一定能够筛全合数。

    简略证明:

    不断地加相当于乘。

    所以实际上我们在做的就是(例如su=2),就是2*2,2*3,2*4,2*5……这些全是合数。

    而且因为起点是平方,所以避免了3*2这样的重复产生,所以更加的快捷。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<map>
    #include<algorithm>
    using namespace std;
    const int INF=2147483647;
    int su[50001]={0};
    bool he[50001]={0};
    int cnt=0;
    bool vis[1000001]={0};
    void Euler(int n){
        for(int i=2;i<=n;i++){
        if(he[i]==0){
            cnt++;
            su[cnt]=i;
        }
        for(int j=1;j<=cnt&&i*su[j]<=n;j++){
            he[su[j]*i]=1;
            if(i%su[j]==0)break;
        }
        }
        return;
    }
    int main(){
        Euler(50000);
        int l,r;
        while(scanf("%d%d",&l,&r)!=EOF){
        memset(vis,0,sizeof(vis));
        int ans=0;
        for(int i=1;i<=cnt&&su[i]<=sqrt(r);i++){
            //t接下来无论怎么变都是合数 
            int t=su[i]*su[i];
            if(t<l)t=l/su[i]*su[i];//t太小的时候就得这样让它变大点 
            if(t<l){
            if(t<=r-su[i]){
                t+=su[i];
            }else continue;
            }
            while(t<=r){
            vis[t-l]=1;
            if(t==su[i])vis[t-l]=0;//压缩空间 
            if(t<=r-su[i])t+=su[i];
            else break;
            }
        }
        if(l==1)vis[0]=1;
        int p=-1;
        int x1,y1,x2,y2,ans1=-1,ans2=INF;
        for(int i=0;i<=r-l;i++){
            if(!vis[i]){
            if(p==-1){p=i;continue;}
            if(ans1<i-p){ans1=i-p;x1=p+l;y1=i+l;}
            if(ans2>i-p){ans2=i-p;x2=p+l;y2=i+l;}
            p=i;
            }
        }
        if(ans1==-1)cout<<"There are no adjacent primes."<<endl;  
            else cout<<x2<<","<<y2<<" are closest, "<<x1<<","<<y1<<" are most distant."<<endl;
        }
        return 0;
    }
  • 相关阅读:
    linux/windows nginx安装
    linux/windows vsftpd安装
    linux 操作命令
    linux/windows java tomcat安装
    常见的Activity Action Intent常量
    Intent.ACTION_PICK
    Android实现抽奖转盘
    Android-短信验证
    Android-多平台分享(新浪微博)
    Android 手势滑动,多点触摸放大缩小图片
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/7898358.html
Copyright © 2020-2023  润新知