1. 简单质数打表-复杂度:O(n*sqrt(n))
分析
所有可能的因数全部试一遍
const int maxn=1e6+5;
int prime[maxn];
void p1()
{
int cnt=0;
for(int i=2;i<maxn;i++)
{
int falg=1;
for (int j=2;j<=sqrt(i);j++)
if (i%j == 0)
flag=0,break;
if(falg)
prime[cnt++]=i;
}
}
2. 质数筛法打表-复杂度:O(n*logn)
分析
先把所有整数列出来,然后把2的倍数全部剔除,然后是3的倍数,4的倍数…以此类推,遍历所有素数,把倍数全部去掉。
对于每个数字i,如果没被去掉,它一定是质数,因为它不是任何2到i-1数字的倍数。然后就开始划它的倍数就好。
const int maxn=1e6+5;
bool vis[maxn];//质数标记为1,非质数标记为0
int prime[maxn];
void p2()
{
int cnt=0;
vis[0]=vis[1]=0;
for(int i=2;i<=maxn;i++) vis[i]=1;
for(int i=2;i<maxn;i++)
{
if(vis[i])
{
prime[cnt++]=i;
for(int j=2*i;j<=maxn;j+=i) //把i的倍数标记为0
vis[j]=0;
}
}
}
3. 欧拉线性质数筛法打表-复杂度:O(n)
分析
普通的质数筛法,很多数被处理了多遍。比如6,质数为2的时候处理了一遍,质数为3的时候又处理了一遍。所以在筛法的基础上改进一下,只允许让最小的质因数晒去,提高了效率。
const int maxn=1e6+5;
bool vis[maxn]={0};//质数标记为0,非质数标记为1
int prime[maxn];
void p3()
{
int cnt= 0;
for (int i=2;i<=maxn;i++)//1不是素数,最小素数为2
{
if (!vis[i]) prime[cnt++]=i;
for(int j=0;j<cnt&&i*prime[j]<=maxn;j++)
{
vis[i*prime[j]] = 1;
if (i%prime[j]== 0) break;
}
}
}