#数论,线性筛,eratosthenes#poj 2689 Prime Distance

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sugar_free_mint/article/details/82024372

题目

在一个区间 [ l . . . r ] ,求两对相邻的质数,一对差值最大,一对最小(可以相同) ( 1 l r 2147483648 ( u n s i g n e d ) )


分析

然而直接跑绝对会TLE,但是可以用试除法的思想可以发现可以跑2到 r 筛一筛(我选离线),然后每次询问筛一筛,就没有什么了,时间复杂度 O ( 47000 + ( r l ) log log ( r l ) )


代码

#include <cstdio>
#include <bitset>
typedef unsigned uit;
uit prime[4793],v[46341],m,l,r;
int main(){
    for (register uit i=2;i<=46340;i++){//线性筛
        if (!v[i]) v[i]=i,prime[++m]=i;
        for (register uit j=1;j<=m;j++){
            if (prime[j]>v[i]||prime[j]>46340/i) break;
            v[i*prime[j]]=prime[j];
        }
    }
    while (scanf("%u%u",&l,&r)==2){//unsigned
        if (l==1) l=2; if (r==1) r=2;
        std::bitset<1000010>v1; v1.reset();
        for (register uit j=1;j<=m;j++)
        for (register uit k=l/prime[j];k<=r/prime[j];k++)
        if (prime[j]*k>=l&&prime[j]*k<=r&&k>1) v1[prime[j]*k-l]=1; //欧式筛
        uit pri2=l,pri1,ans1=0,ans2=r-l<<1,a1,a2,b1,b2;
        while (v1[pri2-l]&&pri2<=r) pri2++;//找到较小的质数
        for (register uit j=pri2;j<=r;j=pri1){
            pri1=j+1;
            while (v1[pri1-l]&&pri1<=r) pri1++;//找较大的质数
            if (pri1<=r&&pri2<=r&&!v1[pri1-l]&&!v1[pri2-l]){
                if (ans1<pri1-pri2) ans1=pri1-pri2,a1=pri2,a2=pri1;
                if (ans2>pri1-pri2) ans2=pri1-pri2,b1=pri2,b2=pri1;
            }
            pri2=pri1;//更新较小的质数
        }
        if (!ans1) printf("There are no adjacent primes.\n");//不存在答案
        else printf("%d,%d are closest, %d,%d are most distant.\n",b1,b2,a1,a2);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sugar_free_mint/article/details/82024372