Prime Distance(求区间素数)

传送门

这道题,其实思路很简单,但是。。坑是很多的


思路

我们发现L,R很大,但是区间只有1e6。

我们知道,R必定包含一个不超过根号R的质因子,所以只需要用筛法求出2~根号R的所有质数,对于每个质数p,把[L,R]中能被p整除的数标记,即标记i*p为合数,最终[L,R]中没被标记的就是质数,一个一个挨着比较就好

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <iostream>
#include <algorithm>
#define N 700003
#define LL long long
#define INF 2100000000
using namespace std;
int not_prime[N],he[1000050];
int prime[N];
int tot=0;
void work(int n)
{
    for(LL i=2;i<=n;++i)
    {
        if(!not_prime[i])
        prime[++tot]=i;
        for(LL j=1;j<=tot&&prime[j]*i<=n;++j)
        {
            not_prime[prime[j]*i]=1;
            if(i%prime[j]==0)break;
        }
    }
}
int main()
{
    LL l,r;
    work(50000);
    while(scanf("%lld%lld",&l,&r)!=EOF)
    {
        if(l==1)l=2;
        memset(he,0,sizeof(he));
        for(int i=1;i<=tot;++i)
        {
            if(prime[i]*prime[i]>r) break;
            int a=l/prime[i];
            a=max(2,a); 
            int b=r/prime[i];
            for(int j=a;j<=b;++j)
               if(j*prime[i]-l>=0)he[j*prime[i]-l]=1;
        }
        LL front=-INF,minn=INF,maxx=-INF;
        int ansmax1=0,ansmax2=0,ansmin1=0,ansmin2=0;
        for(LL i=l;i<=r;++i)//用long long,不然会RE!!! 
        {
            if(he[i-l])continue;
            if(front==-INF){front=i;continue;} 
            else
            {
                if(i-front<minn)ansmin1=front,ansmin2=i,minn=i-front;
                if(i-front>maxx)ansmax1=front,ansmax2=i,maxx=i-front;
                front=i;
             }
        } 
        if(ansmax2==0)printf("There are no adjacent primes.
");
        else printf("%d,%d are closest, %d,%d are most distant.
",ansmin1,ansmin2,ansmax1,ansmax2);
    }
    return 0;
}
poj2689

然后这道题卡了我很久。。真的卡了我很久,不是TLE就是RE。

有两个很大的坑点可能只对于我来说吧

1.RE:L到R的范围是2^31,很容易爆int

如果在最后的循环里这样写

 for(int i=l;i<=r;++i)
View Code

就RE。。。

所以应该用LL


2.TLE

我原来筛[L,R]间的合数是这样写的

for(int i=1;i<=tot;++i)
        {
            if(prime[i]*prime[i]>r) break;
            int j=l/prime[i];
            if(j<2)j=2;
            for(;j*prime[i]<=r;++j)
               if(j*prime[i]-l>=0)he[j*prime[i]-l]=1;
        }
View Code

然后应该这么写

        for(int i=1;i<=tot;++i)
        {
            if(prime[i]*prime[i]>r) break;
            int a=l/prime[i];
            a=max(2,a); 
            int b=r/prime[i];
            for(int j=a;j<=b;++j)
               if(j*prime[i]-l>=0)he[j*prime[i]-l]=1;
        }
View Code

把prime[i]*j放在循环中会TLE。。(污秽之语)


这道题,真的说不出话。。

原文地址:https://www.cnblogs.com/yyys-/p/11222592.html