素数筛法
这一次我们一步一步的来了解素数筛法。
O(nlogn)筛法
一般情况下我们可能比较熟悉的就是O(nlogn)的筛法。
for(int i=2;i<=n;i++)
{
if(!vis[i])
{
for(int j=2;j*i<=n;j++)
vis[j*i]=1;
}
}
时间复杂度计算:
n/1+n/2+…+n/n=nlogn
O(nloglogn)筛法
这个筛法与上述筛法唯一的区别就是在内层循环中的起点由2变为了j,这样时间复杂度就变为了O(nloglogn),是增长速度比较慢的一个筛法。
for(int i=2;i<=n;i++)
{
if(!vis[i])
{
for(int j=i;j*i<=n;j++)
vis[j*i]=1;
}
}
O(n)线性筛
int mindiv[],prime[],tot;
for(int i=2;i<=n;i++)
{
if(!mindiv[i]) mindiv[i]=i,prime[tot++]=i;
for(int j=0;prime[j]*i<=n;j++)
{
mindiv[prime[j]*i]=prime[j];
if(prime[j]!=mindiv[i])
break;
}
}
自我感觉这一个比较好理解,其原理是这样的:对于n以内的数,我们从2开始枚举。
if(i%prime[j]==0)
break;
这一步判断是能够把时间复杂度限制到O(N)的保证。
(代码转自Li Zhuohan)
void getlist(int n)
{
memset(isprime,1,sizeof(isprime));
isprime[1]=false;
for(int i=2;i<=n;i++)
{
if(isprime[i])prime[++primesize]=i;
for(int j=1;j<=primesize&&i*prime[j]<=listsize;j++)
{
isprime[i*prime[j]]=false;
if(i%prime[j]==0)break;
}
}
}