线性筛法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线性筛法相关的知识,希望对你有一定的参考价值。

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

证毕

以上是关于线性筛法的主要内容,如果未能解决你的问题,请参考以下文章

浅谈线性素数筛

素数筛法

线性筛法

常用积性函数的线性筛法整理

简单质数筛法-试除法,Eratosthenes筛法,线性筛法

素数的一般筛法和快速线性筛法