zoukankan      html  css  js  c++  java
  • 素数筛

    摘自博客:https://blog.csdn.net/qq_39826163/article/details/81395306

    一、一般筛素数(埃拉托斯特尼筛法)

    此筛选法的时间复杂度是O(nloglogn)

    //埃氏筛
    bool prime[maxn+5]
    void getprime()  //筛选maxn以内的素数
    {
        int tot=0;
        memset(prime,true,sizeof(prime));
        prime[0]=prime[1]=0;
        for(int i=2;i<=sqrt(maxn);i++)
        {
            if(prime[i])
            {
                for(int j=i*i;j<=maxn;j+=i)
                    prime[j]=0;  //i是素数,则下一个起点是i*i,把后面的所有的i*i+2*n*i筛掉
            }
        }
    }
    这种方法比较好理解,初始时,假设全部都是素数,当找到一个素数时,显然这个素数乘上另外一个数之后都是合数(注意上面的 i*i ,  比 i*2 要快点 ),把这些合数都筛掉。
    但仔细分析能发现,这种方法会造成重复筛除合数,影响效率。比如10,在i=2的时候,k=2*15筛了一次;在i=5,k=5*6 的时候又筛了一次。所以,也就有了快速线性筛法。
     
    二、线性筛素数(欧拉筛法)
    线性筛,复杂度为O(n)。与埃氏筛相比,不会对已经被标记过的合数再进行重复标记,故效率更高。欧拉筛将合数分解为 (最小质因数 * 一个合数) 的形式,通过最小质因数来判断当前合数是否已经被标记过。
    //线性筛(欧拉筛)
    int prime[maxn+5];
    void getprime()
    {
        int tot=0;  //tot用来计数,prime数组用来保存素数,同时标记
        memset(prime,0,sizeof(prime));
        for(int i=2;i<=maxn;i++)
        {
            if(!prime[i])  //如果未被标记表示为素数
                prime[tot++]=i;
            for(int j=0;j<tot&&i*prime[j]<=maxn;j++)//当标记的合数超出范围则退出 
            {
                prime[i*prime[j]]=1;
                if(i%prime[j]==0)  //保证每个合数只会被它的最小质因数筛去,因此每个数只会被标记一次
                    break;
            }
        }
    }
    难点就在于对if (i % prime[j] == 0)这步的理解,意思是每个数保证被它的最小质因数筛出,即当i是prime[j]的整数倍时,记 m = i / prime[j],那么 i * prime[j+1] 就可以变为 (m * prime[j+1]) * prime[j],这说明 i * prime[j+1] 是 prime[j] 的整数倍,不需要再进行标记(在之后会被 prime[j] * 某个数 标记),对于 prime[j+2] 及之后的素数同理,直接跳出循环,这样就避免了重复标记。
     
    欧拉筛素数的其他应用:因为prime[j]必定是prime[j]*i的最小质因子。所以这个性质在某些题里可以用到。
  • 相关阅读:
    python上传阿里云oss
    python调用百度图片识别api
    python实现sm2和sm4国密(国家商用密码)算法
    python坐标获取经纬度或经纬度获取坐标免费模块--geopy
    剑指 Offer 36. 二叉搜索树与双向链表
    vs code中终端中的命令不能使用的解决方法
    VS Code切换默认终端(cmd、powershell)
    剑指 Offer 35. 复杂链表的复制
    剑指 Offer 33. 二叉搜索树的后序遍历序列
    剑指 Offer 32
  • 原文地址:https://www.cnblogs.com/zjl192628928/p/10033967.html
Copyright © 2011-2022 走看看