<学习笔记> 莫比乌斯反演

\(f(n)\)\(g(n)\) 是定义在整数集上的两个函数,满足一下关系:

\[f(n)=\sum_{d \mid n} g(n) \]

但是手摸发现不仅可以从 \(g \rightarrow f\),还可以 \(f \rightarrow g\),发现还满足这个关系:

\[g(n)=\sum_{d \mid n} f(d) \mu(\frac{n}{d}) \]

\(\mu(x) = \begin{cases}1 \qquad x=1 \\ 0 \qquad 存在平方因子 \qquad \\ (-1)^k \qquad k为质因子个数\end{cases}\)

性质一: 对于任意的正整数 \(n\),有 \(\sum_{d \mid n} \mu(d)=\begin{cases}1 \qquad 若n=1 \\ 0 \qquad 若 n >1 \end{cases}\)

证明

\(n=1\) 时,\(\sum_{d \mid n} \mu(d)=1\),成立。

\(n>1\) 时,设 \(n=P_1^{x_1} ... p_k^{x_k}\) ,设 \(d= P_1^{y_1}... P_k^{y_k}\) 。因为 \(y_i > 2\) 全为 \(0\),我们只考虑 \(y_i\)\(0/1\) 的情况,假设 \(d\) 中有 \(r\)\(n\) 的互异质因子,且质因子质数位 \(1\) ,那么对应 $ \mu(d) = (-1)^r$,这样的 \(d\)\(C^r_k\) 个,所以 \(\sum_{d \mid n} \mu(d) = \sum_{r=0}^k C^r_k * (-1)^r =(1-1)^k=0\),其实就是二项式定理。

性质二: \(\mu(n)\) 是积性函数。

证明 易证。

莫比乌斯反演的证明

形式一

\[f(n)=\sum_{d \mid n} g(d) \Rightarrow g(n)=\sum_{d \mid n}f(\frac{n}{d}) * \mu(d) \]

证明一

\[g(n)=\sum_{d \mid n} f(\frac{n}{d}) * \mu(d) = \sum_{d \mid n} \mu(d) \sum_{i \mid \frac{n}{d}} g(i) \]

将上式换成以 \(g(i)\) 为主体的形式,那么有:

\[\sum_{i \mid n}g(i) \sum_{i*d | n} \mu(d) = \sum_{i \mid n}g(i) \sum_{d \mid \frac{n}{i}} \mu(d) \]

根据性质一,只有 \(i=n\) 时才有值,否则全为 \(0\)

综上 \(=g(n)\) 得证。

证明二

\(I(n)=1\)\(id(n)=n\)\(\epsilon(n)=[n=1]\)

单位元 \(\epsilon\) 满足 \(f * \epsilon= f\)

根据狄利克雷卷积得到几个性质:

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

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

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

给出的条件等价于 \(g = f * I\)

根据性质一 \(g * \mu =f * I * \mu=f * \epsilon=f\),得证。

变形

\[f(i) = \sum_{d=1}^{ \lfloor \frac{n}{i} \rfloor} g(d*i) \Rightarrow g(i)= \sum_{d=1}^{ \lfloor \frac{n}{i} \rfloor} f(d*i) \mu(d) \]

证明

\[g(i)= \sum_{d=1}^{ \lfloor \frac{n}{i} \rfloor} f(d*i) \mu(d) = \sum_{d=1}^{ \lfloor \frac{n}{i} \rfloor} \mu(d) \sum_{d_1=1}^{\lfloor \frac{n}{d*i} \rfloor} g(d_1*d*i) \]

\(T=d*d_1\),则有上式

\[=\sum_{T=1}^{\frac{n}{i}}g(T*i) \sum_{d \mid T} \mu(d) \]

根据性质一有,只有当 \(T=1\) 时,原式为 \(g(i)\) , 得证。

莫比乌斯反演的性质

\(g(n)\) 是积性函数的充分必要条件是 \(f(n)\) 是积性函数。

莫比乌斯反演的应用

\(g(i)\) 很难求,但是 \(f(i)\) 很好求,可以根据反演求 \(g(i)\)

\[f(i) = \sum_{d=1}^{ \lfloor \frac{n}{i} \rfloor} g(d*i) \Rightarrow g(i)= \sum_{d=1}^{ \lfloor \frac{n}{i} \rfloor} f(d*i) \mu(d) \]

P4449 于神之怒加强版

\(f(p)\) 表示 \(gcd(i,j)=p\) 的个数,那么 \(Ans=\sum_{p} f(p)*p^k\)

发现 \(f(p)\) 不好求,那么我们设 \(g(p)\) 表示 \(p \mid gcd(i,j)\) 的个数,那么 \(g(p)= \lfloor \frac{n}{p} \rfloor \times \lfloor \frac{m}{p} \rfloor\)

\[g(p)=\sum_{d=1}^{\lfloor \frac{n}{p} \rfloor} f(d*p) \]

\[f(p)=\sum_{d=1}^{\lfloor \frac{n}{p} \rfloor} \mu(d) *g(d*p) \]

\[=\sum_{d=1}^{\lfloor \frac{n}{p} \rfloor} \mu(d) * \lfloor \frac{n}{d*p} \rfloor * \lfloor \frac{m}{d*p} \rfloor \]

那么

\[Ans=\sum_{p=1}^{n}p^k \sum_{d=1}^{\lfloor \frac{n}{p} \rfloor} \mu(d) * \lfloor \frac{n}{d*p} \rfloor * \lfloor \frac{m}{d*p} \rfloor \]

\(T=d*p\) 则有 $$Ans=\sum_{T=1}^{n} \lfloor \frac{n}{T} \rfloor * \lfloor \frac{m}{T} \rfloor \sum_{p \mid T} \mu(\frac{T}{p})*p^k$$

那么我们只需要线性求出 \(\sum_{p \mid T} \mu(\frac{T}{p})*p^k\) 就可以了。

\(g(x)=x*k\),设 \(G(T)=\sum_{p \mid T} \mu(\frac{T}{p})*g(p)\)

首先可以知道 \(G(x)\) 为积性函数,所以 \(G(a*b) =G(a)*G(b) (gcd(a,b)=1)\)

那么我们尝试证明 \(G(a*b) =G(a)*b^k (gcd(a,b) \neq 1)\)

我们设 \(a=p_1^{k_1} ···p_n^{k_n}\),另 \(b=p_t (t \leq n)\)

因为有 \(G(a)=\prod_{i=1}^{n} G(p_i^{k_i})\)

那么就有

\[\frac{G(a*b)}{G(a)} = \frac{G(p_t^{k_t+1})}{G(p_t^{k_t})} \]

\[G(p_t^{k_t})=\sum_{i=0}^{c_t} \mu(pt^i)*g(p_t^{c_t-i}) \]

只有 \(i=0 /1\) 时才有值,那么有

\[G(p_t^{k_t})=g(p_t^{c_t})-g(p_t^{c_t-1}) \]

那么

\[\frac{G(a*b)}{G(a)}= \frac{g(p_t^{c_t+1})-g(p_t^{c_t})}{g(p_t^{c_t})-g(p_t^{c_t-1})}=p_t ^{k} \]

那么我们就可以在线性筛的时候求出,然后计算答案直接整数分块,复杂度 \(O(T \sqrt n)\)

code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5*1e6+10;
const int mod=1e9+7;
int prime[N],nprime[N],mul[N],f[N],sumf[N];
int T,k;
int qpow(int x,int p){
    int ans=1;
    while(p){
        if(p&1) ans=(ans*x)%mod;
        x=(x*x)%mod;
        p>>=1;
    }
    return ans;
}
void get_prime(){
    mul[1]=1;
    f[1]=1;
    for(int i=2;i<=N-10;i++){
        if(!nprime[i]){
            f[i]=(qpow(i,k)-1+mod)%mod;       
            prime[++prime[0]]=i;
            mul[i]=-1;
        }
        for(int j=1;j<=prime[0] && i*prime[j]<=N-10;j++){
            int tmp=i*prime[j];
            nprime[tmp]=1;
            mul[tmp]=mul[i]*mul[prime[j]];
            if(i%prime[j]==0){
                f[tmp]=f[i]*qpow(prime[j],k)%mod;
                mul[tmp]=0;
                break;
            }
            f[tmp]=(f[i]*f[prime[j]]%mod)%mod;
        }
    }
    for(int i=1;i<=N-10;i++) sumf[i]=(sumf[i-1]+f[i])%mod;    
}
signed main(){
    scanf("%lld%lld",&T,&k);
    get_prime();
    while(T--){
		int n,m;
		scanf("%lld%lld",&n,&m);
		if(n>m) swap(n,m);
		int l=1,r=0;
		int ans=0;
		while(l<=n){
			int ta=n/l,tb=m/l;
			if(!ta||!tb) break;
			r=min(n/ta,m/tb);
			ans=(ans+ta*tb%mod*(sumf[r]-sumf[l-1]+mod)%mod)%mod;
			l=r+1;
		}
		printf("%lld\n",ans);
	}
}

DZY Loves Math

首先它让求 \(\sum_{i=1}^n \sum_{j=1}^m F(\gcd(i,j))\)

然后套路的转化为

\[\sum_{x=1}^n F(x) \sum_{d=1}^{\lfloor \frac{n}{x} \rfloor } \mu(d) * \lfloor \frac{n}{xd}\rfloor * \lfloor \frac{m}{xd}\rfloor \]

\(T=xd\) ,则有

\[\sum_{T=1}^{n} \lfloor \frac{n}{T}\rfloor * \lfloor \frac{m}{T}\rfloor *\sum_{x \mid T} F(x) * \mu(\frac{T}{x}) \]

现在只需要求出 \(G(T)=\sum_{x \mid T} F(x) * \mu(\frac{T}{x})\) 就可以整除分块了。

我们设 \(T=p_1^{z_1} ... p_k^{z_k}\)\(x=p_1^{y_1} ... p_k^{y_k}\)

我们设 \(a\) 为最大的 \(z_i\)\(q\) 表示 \(z_i\) 为最大值的个数,\(k\) 为质因子个数。

我们考虑 \(\mu(\frac{T}{d}) \neq 0\),所以 \(y_i=z_i / z_i-1\) , 那么 \(F(x)=a /a-1\)

\(q=k\)

  • 若最大值为 \(F(d)=a\),那么只要满足一个为 \(z_i=y_i\),所以有 (补一位进行二项式定理)

\[\sum_{F(d)=a} F(d)* \mu(\frac{T}{d}) = a* \sum_{F(d)=a} \mu(\frac{T}{d}) = a*\sum_{i=1}^k (-1)^{k-i} C^i_k= a*(\sum_{i=0}^k (-1)^{k-i} C^i_k - (-1)^k )= -a*(-1)^{k} \]

  • 若最大值为 \(F(d)=a-1\),就有

\[\sum_{F(d)=a-1}f(d)*\mu(\frac{T}{d}) = (a-1)*(-1)^k \]

那么这部分答案为 \(g(T)=-a*(-1)^k+(a-1)*(-1)^k = (-1)^{k+1}\)

\(q<k\)

这时不论 \(F(d)=a\) 还是 \(F(d)=a-1\),都需要考虑另外 \(k-q\) 个元素也就是在上式乘上个 \(\sum_{j=0}^{k-q}(-1)^jC^j_{k-q}\) 发现这部分为零,所以这部分的答案为 \(g(T)=0\)

可以用线性筛来求,发现每个数会被最小的质数筛掉,那么我们维护一个 \(mnsum(x)\) 表示 \(x\) 的最小质因子个数, \(excp(x)\) 表示除了最小质因子之外的数,然后求得时候维护。

code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e7+10;
int g[N],mnsum[N],excp[N];
int prime[N];
bool nprime[N];
void get_prime(){
    for(int i=2;i<=N-5;i++){
        if(!nprime[i]){
            prime[++prime[0]]=i;
            g[i]=mnsum[i]=excp[i]=1;
        }
        for(int j=1;j<=prime[0] && i*prime[j]<=N-5;j++){
            int k=prime[j]*i;
            nprime[k]=1;
            if(i%prime[j]==0){
                excp[k]=excp[i];
                mnsum[k]=mnsum[i]+1;
                if(excp[k]==1) g[k]=1;
                else g[k]=(mnsum[excp[k]]==mnsum[k]?-g[excp[k]]:0);
                break;
            }
            excp[k]=i,mnsum[k]=1;
            g[k]=(mnsum[i]==1?-g[i]:0);
        }
    }
    for(int i=1;i<=N-5;i++) g[i]+=g[i-1];
}
signed main(){
    get_prime();
    int T;
    scanf("%lld",&T);
    while(T--){
        int a,b;
        scanf("%lld%lld",&a,&b);
        if(a>b) swap(a,b);
        int l=1,r=0;
        int ans=0;
        while(l<=a){
            int ta=a/l,tb=b/l;
            if(!ta || !tb) break;
            int r=min(a/ta,b/tb);
            ans+=ta*tb*(g[r]-g[l-1]);
            l=r+1;
        }
        printf("%lld\n",ans);
    }
}

[SDOI2015]约数个数和

首先给出结论 \(d(nm)=\sum_{i \mid n}^{j \mid m} [gcd(i,j)=1]\)

证明

\(nm=p_1^{a_1} ... p_k^{a_k}\),那么有 \(d(nm)=\prod_{i=1}^{k} a_i+1\)

\(n=p_1^{b_1} ... p_k^{b_k}\)\(m=p_1^{a_1-b_1} ... p_k^{a_k-b_k}\)

\(i=p_1^{x_1} ... p_k^{x_k}\)\(j=p_1^{y_1} ... p_k^{y_k}\)

要想 \(gcd(i,j)=1\),必须满足 \(x_i=0\)\(y_i=0\)

  • \(x_1=0\) 时,那么 \(y_1\) 可以取 \([0,a_1-b_1]\)

  • \(y_1=0\) 时,那么 \(x_1\) 可以取 \([0,b_1]\)

那么对于第一个质因子,符合条件的组合就有 \(a_1-b_1+1+b_1+1-1=a_1+1\)

以此类推,那么所有符合条件的组合就有 \(\prod_{i=1}^{i=k} a_i+1\)

因此 \(\sum_{i \mid n}^{j \mid m} [gcd(i,j)=1] = \prod_{i=1}^{i=k} a_i+1 = d(nm)\)

回归正题那么原式就为

\[\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{x \mid i}\sum_{y \mid j} [gcd(x,y)=1] \]

\[\sum_{x=1}^{n}\sum_{y=1}^{m} \lfloor \frac{n}{x} \rfloor \lfloor \frac{m}{y} \rfloor [gcd(x,y)=1] \]

\(f(x)=\sum_{x=1}^{n}\sum_{y=1}^{m} \lfloor \frac{n}{x} \rfloor \lfloor \frac{m}{y} \rfloor [gcd(x,y)=x]\)

\(g(x)=\sum_{x=1}^{n}\sum_{y=1}^{m} \lfloor \frac{n}{x} \rfloor \lfloor \frac{m}{y} \rfloor [x | gcd(x,y)]\)

因为 \(\lfloor \frac{n}{dx} \rfloor=\lfloor \frac{\lfloor \frac{n}{dx} \rfloor}{x} \rfloor\) ,设 \(s(n)=\sum_{i=1}^{n}\lfloor \frac{n}{i} \rfloor\),那么 \(g(d)=s(\frac{n}{d})s(\frac{m}{d})\)

根据莫比乌斯反演,就有

\[f(x)=\sum_{d=1}^{n} g(x*d) *\mu(d) \]

因为我们只需要求 $f(1),那么答案就是 \(f(1)=\sum_{d=1}^{n} g(d) *\mu(d)\)

整除分块就可以了。

code
//  P3327 [SDOI2015] 约数个数和 
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=50005;
int mul[N],suml[N];
int prime[N];
bool nprime[N];
void get_prime(){
    mul[1]=1;
    for(int i=2;i<=N-3;i++){
        if(!nprime[i]){
            prime[++prime[0]]=i;
            mul[i]=-1;
        }
        for(int j=1;j<=prime[0] && i*prime[j]<=N-3;j++){
            int k=prime[j]*i;
            nprime[k]=1;
            if(i%prime[j]==0){
                mul[k]=0;
                break;
            }
            mul[k]=mul[prime[j]]*mul[i];
        }
    }
    for(int i=1;i<=N-3;i++){
        suml[i]=suml[i-1]+mul[i];
    }
}
int s[N];
signed main(){
    get_prime();
    int T;
    scanf("%lld",&T);
    for(int n=1;n<=N-3;n++){
        int l=1,r=0;
        while(l<=n){
            int t=n/l;
            if(!t) break;
            int r=n/t;
            s[n]+=(r-l+1)*t;
            l=r+1;
        }
    }
    while(T--){
        int n,m;
        scanf("%lld%lld",&n,&m);
        if(n>m)  swap(n,m);
        int ans=0;
        int l=1,r=0;
        while(l<=n){
            int ta=n/l,tb=m/l;
            if(!ta || !tb) break;
            int r=min(n/ta,m/tb);
            ans+=s[ta]*s[tb]*(suml[r]-suml[l-1]);
            l=r+1;
        }
        printf("%lld\n",ans);
    }
}
posted @ 2023-08-14 06:47  _bloss  阅读(61)  评论(0)    收藏  举报