线性筛法

Posted WeiAR

tags:

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

关于线性筛法

线性是指O(n)内筛掉所有合数,还有一种方法叫埃氏筛法,我先证明埃氏筛法效率低,也就是会有重复。

证明如下:

埃氏筛法的原理是找到一个素数后,它的1~n倍就会被筛掉,任何一个合数都可以被拆成一个质数*合数的形式,我们对每一个质数对应的可能的(合)数都枚举了,这就保证了所有可能的合数都被筛掉了。为什么不是最优呢?问题出在那个质数上,对于一个合数m,m=h*P,P是质数且P>m的最小质因数,那么m也可以表示为m=H*p,(H是个比h大的合数,p是m的最小质因数),这样我们在枚举p的倍数时,m就被筛掉了,而在枚举P的倍数时,m又被筛掉了一次,造成效率浪费。

怎办呢?--------线性筛法

我们在枚举倍数时,保证当前质数不能整除这个倍数就好了,也就是p是m的p,这样我们在最优性的条件下,对每一个质数,它所有对应的倍数,都被枚举到,也就保证了可行性。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,cnt;
int prime[100000];
bool vis[100000];

void Euler()
{
    for(int i=2;i<=n;i++)
    {
        if(!vis[i]) prime[++cnt]=i;
        for(int j=1;j<=cnt&&i*prime[j]<=n;j++)
        {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)
            break;
        }
    }
}

int main()
{
  cin>>n;
  Euler();
  for(int i=1;i<=cnt;i++)
  cout<<prime[i]<< ;
  return 0;
}

里面关键就是那个break,如果不break,就是再往大里枚举,那么以后枚举到的质数,一定不是最小质数,因为它都比当前质数大了,怎么可能最小,最小也只可能是当前的质数,从而实现了优化。

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

浅谈线性素数筛

素数筛法

线性筛法

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

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

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