1.埃氏筛,算法复杂度为,思想很简单,我们知道2是素数,那么2的倍数一定不是素数,那么这些数我们就可以无需进行素数判断,同理3是素数,那么3的倍数……于是,先把N个素数排列起来,从2开始,2的倍数全部标记为合数,再把3的倍数标记为合数,一直做下去,就能把不超过N的所有合数筛掉。代码如下:
#include <iostream>
#include <cmath>
#define maxn 10000005
bool a[maxn]={0};//判断标记数组,初始为0
int prime[maxn];
using namespace std;
int main(){
int n,m;
cin>>n;
for(int i=2;i<=sqrt(n)+1;i++)
if(a[i]==0)//i为素数
for(int j=i;i*j<=n;j++) a[i*j]=1;//标记i的倍数为合数,把j初始i,小优化
m=0;
for(int i=2;i<=n;i++)
if(!a[i]) prime[m++]=i;//素数a[i]为0
for(int i=0;i<m;i++) cout<<prime[i]<<' ';
return 0;
}
2.欧拉筛
在上面筛选过程中,存在重复筛选的情况,比如12会被2和3重复筛,如果我们能避免重复筛选,那么算法效率可以大大提高至,思路为如果i为素数,那么i乘以小于i的素数,筛选的数跟之前筛出来的不会重复。代码如下:
#include <iostream>
#define maxn 10000005
int a[maxn]={0},prime[maxn];
using namespace std;
int main(){
int n,i,j;
cin>>n;
int num=0;
for(int i=2;i<n;i++){
if(!a[i]) prime[num++]=i;//将素数存进去
for(int j=0;j<num && i*prime[j]<n;j++){//筛去i*prime数组的元素
a[i*prime[j]]=1;
if(!i%prime[j]) break;//如果i被prime数组元素整除,退出,避免重复筛选
}
}
for(int i=0;i<num;i++) cout<<prime[i]<<' ';
return 0;
}