关于线性筛法

线性是指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,就是再往大里枚举,那么以后枚举到的质数,一定不是最小质数,因为它都比当前质数大了,怎么可能最小,最小也只可能是当前的质数,从而实现了优化。