筛法的思路:
对于不超过n的每个非负整数p,删除2p,3p,4p,…,当处理完所有数之后,剩下的就是素数。如果用prime[i]表示i是否是素数,筛法的代码可以写成:
memset(prime,true,sizeof(prime));
prime[0]=prime[1]=false;
for(int i=2;i<=maxn;i++)
{
for(int j=i*2;j<maxn;j+=i)
{
prime[j]=false;
}
}
下面来改进一下这份代码:
1.我们可以把上面的p只限定于素数,因为对于一个合数来说,它和它的倍数已经被它的素因数给筛选过了
2.既然我们把p只限定于素数,那么第一重的循环就没必要到n了,到sqrt(n+0.5)就可以了,因为合数一定至少有一个不大于sqrt(n)约数,只要找到这个数就可以了
3.内层循环也没必要从2*i开始,因为它在i=2的时候就已经被筛选过了,所以可以直接j=i*i开始,因为j=i*k,k < i时他们都已经被筛选过了
最优代码:
memset(prime,true,sizeof(prime));
prime[0]=prime[1]=false;
int n=sqrt(maxn+0.5);
for(int i=2;i<=n;i++)
{
if(prime[i])
{
for(int j=i*i;j<maxn;j+=i)
{
prime[j]=false;
}
}
}