zoukankan      html  css  js  c++  java
  • 线性筛法

    2016.1.25

     

    学习完了伪线性的埃式筛法,我们来学习一个真线性的线性筛法。

    时间复杂度:O(n)(即每个合数只会被筛一遍)

    操作: 每当我们在外循环(外循环与埃式筛法相同)遇到一个素数时,我们将所有已筛得的素数(包括该素数)分别与该素数的乘积筛去;每当我们遇到一个合数时,则该合数可以表示为A=p1*p2*p3*……pk, pi<=pj (i<=j),那么我们筛去所有小于等于p1的素数分别与A的乘积。

    代码如下:

    int n,prime[1000005],e;
    bool is_prime[1000005];//is_prime为0表示为素数 
    void solve()//线性筛 
    {
        prime[0]=prime[1]=1;
        for(int i=2;i<=n;i++)
        {
            if(!is_prime[i]) 
                prime[++e]=i;
    
                    //无论i是否为素数都会执行到这一步,因为上述操作对于合数和素数是可以统一的
            for(int j=1;j<=e && i*prime[j]<=n;j++)
            {
                is_prime[i * prime[j]]=1;
                if(i % prime[j] == 0) break;//若i为素数,则这步不会执行;若i为合数,则prime[j]等于i中最小质因数时停止。
            }
        }
    }
    View Code

    这个操作执行起来并不难,代码也容易看懂,关键是证明。

    关于为什么当遇到合数A时只筛小于等于p1的素数与A的乘积:比如我们筛了一个比p1大的素数pn与A的乘积即pn*p1*p2*p3*……pk,那么当我们遇到pn*p2*p3*p4*……*pk时会再次筛掉pn*p1*p2*p3*……pk。

    关于为何合数都会被筛除并且只筛一次:对于我们每遇到一个合数时,则该合数可以表示为A=p1*p2*p3*……pk, pi<=pj (i<=j),那么在这之前我们遇到的能筛掉A的B必须等于p2*p3*……pk, pi<=pj (i<=j),因为根据我们的操作,A/B必须不大于B中任意一个质因数,所以B有且只有一个,所以每个合数会且只会被筛一次。

    证毕

  • 相关阅读:
    jquery的$().each,$.each的区别
    前端面试题整理
    JS中Null与Undefined的区别
    LESS介绍及其与Sass的差异(转载自伯乐在线,原文链接:http://blog.jobbole.com/24671/)
    APP 弱网测试
    ADB命令
    pytest之参数化parametrize的使用
    APP测试
    python 异常捕捉
    pip 安装依赖 requirements.txt
  • 原文地址:https://www.cnblogs.com/16er/p/5158938.html
Copyright © 2011-2022 走看看