素数筛选法的思想:对于不超过N的每个正整数,删除2P,3P,4P……,当处理完所有数之后,还没有被删除的就是素数。
按照上述思想写成的简单筛选法代码如下:
memset(vis,o,sizeof(vis));
for(int i=2;i<N;i++)
for(int j=i*2;j<=N;j+=i) vis[j]=1;
//用vis数组存储数j是否被删除的信息。
下面我们想想如何改进:
1.由唯一分解定理:每个正整数可以写成n=a1^p1*a2^p2……(其中a1,a2是质数)
改进代码:
这个改进了的代码也会有重复筛选的情况存在,比如数16,81等
下面给出最优的欧拉筛法,真正的o(n)复杂度
欧拉筛法和第二个代码 思想类似,只是多了关键了一步,“ifi%prime[j]==0) break;"
为什么要这样做呢?
分析第二个代码,它极大地避免了重复的筛选,它的外层筛选只选取质数,内层循环避免了2*3和3*2的这种重复筛选
但是像24这种既可以分解为2*12,又可以分解为3*8的来说,第二个代码就没有避免对24的重复筛选。
下面给出欧拉筛法里面关键一步的原理证明