这是一个可以在线性时间内筛出素数的神奇筛子,我们先看一下它长啥样:
void xxsifter()
{
for(int i=2;i<MAXM;i++)
{
if(!b[i])
{
pr[++tot]=i;
}
for(int j=1;pr[j]*i<MAXM;j++)
{
b[pr[j]*i]=1;
if(i%pr[j]==0)
{
break;
}
}
}
}
简单的说,每个合数数都会被自己最小的素因数筛去,假设一个合数可以表示成pr[j]*i那么当外层循环到了i,内层循环到了j时会被筛掉,用于pr[j]是最小的素因数,所以j不会提前退出,一定可以筛到的。
有了这个筛子当模板,我们还可以筛出欧拉函数φ和莫比乌斯函数μ。
由于φ(ab)=φ(a)*φ(b)(GCD(a,b)==1)我们可以快速筛出φ。
筛φ:
void xxsifter()
{
phy[1]=1;
for(int i=2;i<MAXM;i++)
{
if(!b[i])
{
pr[++tot]=i;
phy[i]=i-1;
}
for(int j=1;pr[j]*i<MAXM;j++)
{
b[pr[j]*i]=1;
if(i%pr[j]==0)
{
phy[pr[j]*i]=phy[i]*pr[j];
break;
}
else
phy[pr[j]*i]=phy[i]*phy[j];
}
}
}
莫比乌斯函数μ
百度上的:
莫比乌斯函数完整定义的通俗表达:
1)莫比乌斯函数μ(n)的定义域是N
2)μ(1)=1
3)当n存在平方因子时,μ(n)=0
4)当n是素数或奇数个不同素数之积时,μ(n)=-1
5)当n是偶数个不同素数之积时,μ(n)=1
筛μ
void xxsifter()
{
mu[1]=1;
for(int i=2;i<=MAXN;i++)
{
if(vis[i]==0)
{
pr[++tot]=i;
mu[i]=-1;
}
for(int j=1;pr[j]*i<=MAXN;j++)
{
vis[pr[j]*i]=1;
if(i%pr[j]==0)
break;
mu[pr[j]*i]=-mu[i];
}
}
}
不过这都是最基本的板,如果题目有需要可以添油加醋。