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.\n");
    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.\n",minl,minr,maxl,maxr);
    }
}

int main()
{
    p1();
    while(scanf("%lld%lld",&l,&r)!=EOF)
    {
        solve();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xiongtao/p/10738646.html
今日推荐