杜教筛

杜教筛

前置知识

积性函数:对于任意的\(\gcd(i,j)=1\)\(f(i)\times f(j)=f(ij)\)

完全积性函数:对于任意的\(i,j\)\(f(i)\times f(j)=f(ij)\)

\(\epsilon(x)=[x==1]\)\(I(x)=1\)\(id(x)=x\)\(\sigma_k(x)=\sum\limits_{d|x}d^k\)

狄利克雷卷积

\((f*g)(n)=\sum\limits_{d|n}f(d)g(\frac{n}{d})\)

推论:

1.\(\mu*I=\epsilon\)

证明:当\(n=1\)时上式显然为1,当\(n>1\)时,根据唯一分解定理,设\(n=p_1^{a_1}p_2^{a_2}\cdots p_k^{a_k}\),根据\(\mu\)的定义,若\(a_i>1\)\(\mu(d)\)为0,则\(\sum\limits_{d|n}\mu(d)=\sum\limits_{i=0}^k\binom{k}{i}(-1)^i=(1-1)^k=0\)

2.\(\varphi*I=id\)

证明:当\(n=p^m\)时,\(\sum\limits_{d|n}\varphi(d)=\varphi(1)+\sum\limits_{i=1}^m\varphi(p^i)=1+\sum\limits_{i=1}^m(p^i-p^{i-1})=p^m=n\)

\(n\)为任意整数时,令\(n=\prod p^m\),则\((\varphi*I)(\prod p^m)=\prod(\varphi*I)(p)=\prod p^m=n\)

3.\(\mu*id=\varphi\)

证明:

\[id=\varphi*I \]

\[\mu*id=\varphi*(I*\mu) \]

\[\mu*id=\varphi*\epsilon=\varphi \]

莫比乌斯反演

\[g(n)=\sum\limits_{d|n}f(d) \]

\[f(n)=\sum\limits_{d|n}\mu(d)g(\frac{n}{d}) \]

证明:因为\(g=(f*I)\),所以\(g*\mu=f*I*\mu=f*(I*\mu)=f*\epsilon=f\)

杜教筛

杜教筛是用来快速求积性函数前缀和的方法。具体来说,我们设\(S(n)=\sum\limits_{i=1}^nf(i)\),再找一个积性函数\(g(x)\),考虑\((f*g)\)的前缀和

\[\sum\limits_{i=1}^n(f*g)(i)=\sum\limits_{i=1}^n\sum\limits_{d|i}f(d)g(\frac{i}{d})=\sum\limits_{d=1}^ng(d)\sum\limits_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}f(i)=\sum\limits_{d=1}^ng(d)S(\left\lfloor\frac{n}{d}\right\rfloor) \]

我们把\(g(1)S(n)\)提出来,就是\(g(1)S(n)=\sum\limits_{i=1}^ng(i)S(\left\lfloor\frac{n}{i}\right\rfloor)-\sum\limits_{i=2}^ng(i)S(\left\lfloor\frac{n}{i}\right\rfloor)\),我们发现,前一项\(\sum\limits_{i=1}^ng(i)S(\left\lfloor\frac{n}{i}\right\rfloor)\)由前面推导可知为\(\sum\limits_{i=1}^n(f*g)(i)\),于是得到了杜教筛的核心式子:

\[g(1)S(n)=\sum\limits_{i=1}^n(f*g)(i)-\sum\limits_{i=2}^ng(i)S(\left\lfloor\frac{n}{i}\right\rfloor) \]

这就意味着,只要我们找到一个可以快速计算\((f*g)\)的前缀和的\(g(x)\),我们就可以用数论分块递归求解\(S(n)\),时间复杂度是\(O(n^{\frac{3}{4}})\),如果我们预处理前\(n^{\frac{2}{3}}\)个答案,我们就可以把复杂度降到\(O(n^{\frac{2}{3}})\)

一些应用

1.求\(\mu\)的前缀和

因为\(\mu*I=\epsilon\),所以把\(I(x)\)当做\(g(x)\)即可,而且前缀和超好求。

代码:

inline int calcmu(int x){
    if(x<=M)return summu[x];
    if(mp.find(x)!=mp.end())return mp[x];
    int ans=1;
    for(int l=2,r;l<=x;l=r+1){
        r=x/(x/l);
        ans=(ans-(r-l+1)%p*calcmu(x/l)%p)%p+p)%p;
    }
    return mp[x]=ans;
}

2.求\(\varphi\)的前缀和

因为\(\varphi*I=id\),所以把\(I(x)\)当做\(g(x)\)即可。

代码:

inline int calcphi(int x){
    if(x<=M)return sumphi[x];
    if(mp.find(x)!=mp.end())return mp[x];
    int ans=x*(x+1)/2%p;
    for(int l=2,r;l<=x;l=r+1){
        r=x/(x/l);
        ans=(ans-((r-l+1)%p*calcphi(x/l)%p)%p+p)%p;
    }
    return mp[x]=ans;
}

例题

1.P4213 【模板】杜教筛(Sum)

就是求\(\mu,\varphi\)的前缀和,直接套板子。

2.P3768 简单的数学题

题意:求\(\sum\limits_{i=1}^n\sum\limits_{j=1}^nij\gcd(i,j)\)

思路:

\[\sum\limits_{i=1}^n\sum\limits_{j=1}^nij\gcd(i,j)=\sum\limits_{i=1}^n\sum\limits_{j=1}^nij\sum\limits_{k|i,k|j}\varphi(k) \]

\[=\sum\limits_{k=1}^n\varphi(k)\sum\limits_{k|i}\sum\limits_{k|j}ij \]

\[=\sum\limits_{k=1}^n\varphi(k)k^2(\sum\limits_{i=1}^{\left\lfloor{\frac{n}{k}}\right\rfloor}i)^2 \]

然后考虑怎么求前一项
\(f=\mu*id*id\)\(g=id*id\),则\((f*g)(n)=\sum\limits_{d|n}(\varphi(d)d^2)(\frac{n}{d})^2=n^3\),这样就又可以愉快套板子了。

inline int calc(int x){
    if(x<=M)return sumphi[x];
    if(mp.find(x)!=mp.end())return mp[x];
    int ans=S2(x);
    for(int l=2,r;l<=x;l=r+1){
        r=x/(x/l);
        ans=(ans-((S1(r)-S1(l-1)+p)%p*calc(x/l)%p)%p+p)%p;
    }
    return mp[x]=ans;
}
inline int solve(){
    int ans=0;
    for(int l=1,r;l<=n;l=r+1){
        r=n/(n/l);
        ans=(ans+(calc(r)-calc(l-1)+p)%p*S2(n/l)%p)%p;
    }
    return ans;
}
posted @ 2023-03-14 21:38  Xttttr  阅读(26)  评论(0编辑  收藏  举报