zoukankan      html  css  js  c++  java
  • 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。。(污秽之语)


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

  • 相关阅读:
    面试C#需要准备的一些基础
    学习jQuery(一),做的第一个可拖动列的Grid
    面试的两道SQL题
    SSIS ODBC方式连接mysql数据库的一个问题
    WIN7下A卡解决部分游戏(CS、CF等)无法全屏问题
    显示Deprecated: Assigning the return value of new by reference is deprecated in解决办法
    Eclipse 中文插件的安装
    安装NASM for Linux
    将Eclipse中文注释字体变大方法
    如何查看局域网内所有IP
  • 原文地址:https://www.cnblogs.com/yyys-/p/11222592.html
Copyright © 2011-2022 走看看