最正常的从2枚举到sqrt(n)的求素数表的方法的时间复杂度是O(n*sqrt(n)),在10^5级别以内是没有什么问题的,但是超过10^5就可能会力不从心了。
记录一下比较容易理解的一种求素数的筛法,即Eratosthenes筛法,时间复杂度可以达到O(n)。还有更有的欧拉筛法,等学习到再补充。
算法:
从小到大枚举所有数,对每一个素数,筛去它的所有倍数,剩下的就都是素数。(从2开始,以2为开端进行“筛”)
p.s.:
读者可以自己举一个例子对算法进行模拟,会发现:当从小到大达到某个a时,如果a没有被前面的步骤筛掉,那么a一定是素数。因为,如果a不是素数,那么a一定有小于a的素数因子,这样在之前的步骤中,a进一定是其素数因子的倍数,从而被筛掉。所以,当枚举到a时,它还没被筛掉,说明a一定是素数。
代码实现:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
const int maxn = 105;
bool book[maxn] = {false}; //筛选数组,当book[i]==true时表示i被筛掉
int prime[maxn], num = 0;
void findPrime(int n){
for(int i = 2; i < n; i++){
if(book[i] == false){
prime[num++] = i;
for(int j = i+i; j < n; j+=i){
book[j] = true;
}
}
}
}
int main(){
scanf("%d",&n);
findPrime(n);
//print prime table
for(int i = 0; i < num; i++){
printf("%d ",prime[i]);
}
printf("\n");
return 0;
}