• poj 2689 Prime Distance(素数筛)


    题目链接:http://poj.org/problem?id=2689

    题意:给出区间l,r(1<=l<r<=2147483647),要找到出相邻素数距离最小和距离最大各一对,如果有多对,输出最初的。

    思路:解决这个题目首先需要将[l,r]范围的所有素数找出来,但是l,r范围太大,全找出来是不可能的。因为题目给出l和r的差不超过1000000,将sqrt(r)内的素数打个表, 再用 它去筛选 [l, r] 内的合数, 然后再遍历一次 [l, r], 记录答案即可,这样找素数时间复杂度为O(sqrt(r)),遍历时间复杂度为O(r-l),不会超时。

    代码

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn=50005;
    const int maxm=1e6+10;
    int prime1[maxn];
    bool  isprime[maxm];
    int nprime1,nprime2;
    ll l,r,prime2[maxm];
    void p1()//打表1~sqrt(r)里的素数 
    {
        nprime1=0;
        memset(isprime,1,sizeof(isprime));
        for(ll i=2;i<maxn;i++)
        {
            if(isprime[i])
                prime1[++nprime1]=i;
            for(int j=1;j<=nprime1;j++)
            {
                if(i*prime1[j]>maxn)
                    break;
                isprime[i*prime1[j]]=0;
                if(i%prime1[j]==0)
                    break;
            }
        }
    }
    
    void p2()
    {
        memset(isprime,1,sizeof(isprime));
        for(ll i=1;i<=nprime1;i++)
        {
            ll sum=l/prime1[i];
            while(sum*prime1[i]<l||sum<=1)//使sum*prime1[i]>=l且不是素数 
                sum++;
            for(ll j=sum*prime1[i];j<=r;j+=prime1[i])
            {
                if(j>=l)//筛掉[l,r]中的合数 
                    isprime[j-l]=0;
            }
        }
        if(l==1)
            isprime[0]=0;
    }
    
    void solve()
    {
        ll maxx=-inf,minx=inf;
        ll minl,minr,maxl,maxr;
        p2();
        nprime2=0;
        for(int i=0;i<=r-l;i++)//遍历[l,r],保存其中的素数。 
        {
            if(isprime[i])
                prime2[++nprime2]=i+l;
        }
        if(nprime2<=1)
            printf("There are no adjacent primes.
    ");
        else
        {
            for(int i=1;i<nprime2;i++)
            {
                if(prime2[i+1]-prime2[i]>maxx)
                {
                    maxx=prime2[i+1]-prime2[i];
                    maxl=prime2[i],maxr=prime2[i+1];
                }
                if(prime2[i+1]-prime2[i]<minx)
                {
                    minx=prime2[i+1]-prime2[i];
                    minl=prime2[i],minr=prime2[i+1];
                }
            }
            printf("%lld,%lld are closest, %lld,%lld are most distant.
    ",minl,minr,maxl,maxr);
        }
    }
    
    int main()
    {
        p1();
        while(scanf("%lld%lld",&l,&r)!=EOF)
        {
            solve();
        }
        return 0;
    }
  • 相关阅读:
    NOI2007项链工厂——sbTreap代码
    终于还是卡着进队了
    SCOI RP+=INF
    每日算法——新型在线LCA
    每日算法——并查集的应用
    每日算法--矩阵乘法优化递推
    神一般的数据结构--可持久化treap
    算法竞赛中的数论经典定理
    Baby Step Gaint Step
    素数分组 哥德巴赫猜想
  • 原文地址:https://www.cnblogs.com/xiongtao/p/10738646.html
Copyright © 2020-2023  润新知