杜教筛

杜教筛可以在非线性时间内求积性函数前缀和

比如我们对积性函数\(f\),我们要求\(S(n)=\sum\limits^{n}_{i=1}f(i)\)

先通过构造得积性函数\(h\)\(g\),使得\(h=f \times g\),并且可以快速计算\(h\)\(g\)的前缀和

\[\begin{aligned} &\sum\limits^{n}_{i=1}h(i) \\ =&\sum_{i=1}^{n}\sum_{d \mid i}f(\frac{i}{d})g(d) \\ =&\sum_{d=1}^{n}g(d)S(\lfloor \frac{n}{d} \rfloor) \\=&g(1)S(n)+\sum_{d=2}^{n}g(d)S(\lfloor \frac{n}{d} \rfloor) \\&g(1)S(n)=\sum\limits^{n}_{i=1}h(i)-\sum_{d=2}^{n}g(d)S(\lfloor \frac{n}{d} \rfloor) \end{aligned} \]

预处理\(f\)的前\(n^{\frac{2}{3}}\)项,后\(n^{\frac{1}{3}}\)项递归计算,时间复杂度为\(O(n^{\frac{2}{3}})\)

对于\(\mu\)\(μ \times 1=\epsilon\),构造\(g=1,h=\epsilon\)

对于\(\varphi\)\(\varphi \times 1=id\),构造\(g=1,h=id\)

\(code:\)

void init()
{
    mu[1]=phi[1]=1;
    for(ll i=2;i<=all;++i)
    {
        if(!tag[i]) pri[++tot]=i,mu[i]=-1,phi[i]=i-1;
        for(ll j=1;j<=tot;++j)
        {
            ll k=i*pri[j];
            if(k>all) break;
            tag[k]=true;
            if(i%pri[j]) mu[k]=mu[i]*mu[pri[j]],phi[k]=phi[i]*phi[pri[j]];
            else
            {
                mu[k]=0,phi[k]=phi[i]*pri[j];
                break;
            }
        }
    }
    for(int i=1;i<=all;++i) mu[i]+=mu[i-1],phi[i]+=phi[i-1];
}
ll getphi(ll n)
{
    if(n<=all) return phi[n];
    if(s_phi[n]) return s_phi[n];
    ll ans=n*(n+1)/2;
    for(int l=2,r;l<=n;l=r+1)
        r=n/(n/l),ans-=(r-l+1)*getphi(n/l);
    return s_phi[n]=ans;
}
ll getmu(ll n)
{
    if(n<=all) return mu[n];
    if(s_mu[n]) return s_mu[n];
    ll ans=1;
    for(int l=2,r;l<=n;l=r+1)
        r=n/(n/l),ans-=(r-l+1)*getmu(n/l);
    return s_mu[n]=ans;
}
posted @ 2020-02-13 21:21  lhm_liu  阅读(306)  评论(0编辑  收藏  举报