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