版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LightInDarkness/article/details/82562034
学习到一种高效的筛选素数的方法——埃拉托色尼筛选法,如果要选出[2, n]范围内的素数,可以参考以下步骤:
1.构造一个[2, n]范围的数组,全部标记为1(true)。
2.删除掉数组中的非素数,将其标记为0(false)。
①:删除2的倍数
②:删除3的倍数
③:删除4的倍数(没有必要,已经在①中删除了)
④:删除5的倍数
⑤:……
3.直到不能继续删除为止。如此留下的就是质数了。
原理是显而易见的,没有必要多做解释。先上代码:
#include<iostream>
#define n 10000
using namespace std;
int main(){
int prime[n + 1];
//初始化数组
for(int i = 0; i < n + 1; i++)
prime[i] = 1;
//筛选素数
for(int i = 2; i * i <= n; i++){
if(prime[i] == 1){
int j = i * i;
while(j <= n){
prime[j] = 0;
j += i;
}
}
}
//输出
for(int i = 2; i < n + 1; i++)
if(prime[i] == 1)
cout << i << '\t';
}
先看这部分代码:
if(prime[i] == 1){
int j = i * i;
while(j <= n){
prime[j] = 0;
j += i;
}
}
意思是如果i是素数,会去除i * i, i * (i + 1), i * (i + 2), i * (i + 3), ...... , i * (i + m)。(其中i * (i + m) <= n)
那2i, 3i, 4i, ...... i * (i - 1)怎么办呢?实际上,我们已经早就把这些数删掉了。因为我们在去除i的倍数以前,早就已经去除了2, 3, 4, ......, i - 1的倍数。而我们省去的那部分数也正是这些数的倍数,所以就无需再次删除了。
在理解了这个的基础上,我们再来看看for循环中i * i <= n的条件。实际上就是要求i <= floor(√n)。当i == floor(√n)时,只需要处理i * i( <= n)之后i的倍数即可, 前面的已经被其他数的倍数去除了。此时若i += 1,那么i实际上删除的倍数则在n之后,对于题目要求而言就没什么必要了。