【数学】线性筛

这是一个可以在线性时间内筛出素数的神奇筛子,我们先看一下它长啥样:

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];
        }
    }
}

不过这都是最基本的板,如果题目有需要可以添油加醋。

猜你喜欢

转载自blog.csdn.net/qq_35713030/article/details/82316055