• 线性筛法


    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有且只有一个,所以每个合数会且只会被筛一次。

    证毕

  • 相关阅读:
    Android 查看APK文件的签名算法
    Android 查看App冷启动时间/热启动时间/页面打开时间
    Android 查看Apk签名方式V1和V2
    Android App启动速度优化
    Android SharedPreferences中apply和commit的效率差距
    Gralde 网络代理
    Git 将子文件夹分离为一个新的库
    Fabric-Crashlytics-Android 注意点
    Gradle编译失败 generating the main dex list
    Gralde 同步失败
  • 原文地址:https://www.cnblogs.com/16er/p/5158938.html
Copyright © 2020-2023  润新知