zoukankan      html  css  js  c++  java
  • 区间质数查询 luoguP1865

    原题 https://www.luogu.org/problemnew/show/P1865

    本来get到了一个很好的判断素数的方法

    O(玄学常数)https://www.luogu.org/blog/nopartyfoucaodong/solution-p3383 (我的luogu博客 嘻嘻)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int n,m;
    bool su(int a){
        if(a==1) return 0;
        if(a==2||a==3) return 1;
        if(a%6!=1&&a%6!=5) return 0;
        int temp=sqrt(a);
        for(int i=5;i<=temp;i+=6)
        {
            if(a%i==0||a%(i+2)==0) return 0;
        }
        return 1;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int x;
            scanf("%d",&x);
            if(su(x)) printf("Yes"),cout<<endl; //是质数
            else printf("No"),cout<<endl;
            x=0; 

    }
    return 0; }

     然而这个方法在一些时候是有弊病的。比如本题区间质数查询时,有些数需要重复的判断多次。用这个方法就会T掉部分点。

    一位@Enderturtle大佬给出了另一种方法。

    所以说,对于不同的方法,还要注意看它们的优点,适宜什么情况啊(叹气

    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,m;
    int tot[1000005];
    bool book[1000005];
    void prime(int f)
    {
        tot[1]=0;
        book[1]=true;
        for(int i=2;i<=f;i++)
        {
            if(book[i]==false)
            {
                tot[i]=tot[i-1]+1;
                for(int j=2*i;j<=f;j=j+i)
                {
                    book[j]=true;
                }
            }
            else tot[i]=tot[i-1];
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        prime(m);
        for(int i=1;i<=n;i++)
        {
            int l=0,r=0;
            scanf("%d%d",&l,&r);
            if(l<1||l>m||r<1||r>m)
            {
                printf("Crossing the line
    ");
                continue;
            }
            else 
            {
                if(book[l]==false)
                {
                    printf("%d
    ",tot[r]-tot[l]+1);
                    continue;
                }
                printf("%d
    ",tot[r]-tot[l]);
            }
            
        }
        return 0;
    }

    所以我们换个角度从判断素数,变成判断合数;

    合数显然是可以分解质因数的,既然如此,也就说明,质数的倍数(倍数>1)都是合数,所以就有了线性筛(不懂线性筛的同学可以看洛谷[【模板】线性筛素数](https://www.luogu.org/problemnew/show/3383 "【模板】线性筛素数"))

    本质上就是从2开始把它除本身的倍数全部删去,以此类推(这时你可能要问那到这个数的时候怎么判断它是不是质数,事实上,如果自然数N在N-1的时候没有把它标记掉就肯定是质数(具体证明可百度))

    区间和可以用前缀和处理;

    f[r]-f[l],如果l是质数还要加1

  • 相关阅读:
    [Shoi2007]Vote 善意的投票
    [CQOI2015]任务查询系统
    [SDOI2013]森林
    HttpClient 教程 (二)
    /system改成可写
    Netbeans 6.8 + apktool_2.0.0b9 动态调试smali文件
    把中文版NetBeans改成英文版
    ZjDroid工具介绍及脱壳详细示例
    grep过滤搜索
    android Log图文详解(Log.v,Log.d,Log.i,Log.w,Log.e)
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/8900515.html
Copyright © 2011-2022 走看看