莫比乌斯函数及其反演

一些定义

数论函数
定义域为正整数的函数,一般分类如下:

  1. 积性函数
    对于 \(\forall x,y \in N , gcd(x,y)=1\) ,若 \(f(x \cdot y)=f(x) \cdot f(y)\) ,则 \(f\) 是积性函数。
  2. 完全积性函数
    对于 \(\forall x,y \in N\) ,若 \(f(x \cdot y)=f(x) \cdot f(y)\) ,则 \(f\) 是完全积性函数。
  3. 非积性函数

狄利克雷卷积
可以理解为数论函数的乘法,常用符号 \(*\) 表示。
\(f,g\) 均为数论函数,则有 \((f*g)(n) = \sum_{d|n}f(d)g(\frac{n}{d})\)
对于数论函数乘法,其单位元函数为 \(e\)

\[e(n) = \begin{cases} 1\ , n=1 \\ 0\ , n \ne 1 \end{cases} \]

即对于任意数论函数 \(f\) ,都有 \(f*e=f\)
狄利克雷卷积满足交换律和结合律

莫比乌斯函数

莫比乌斯函数 \(\mu\) 的定义如下:

\[\mu(n) = \begin{cases} 1\ , n=1 \\ 0\ , n包含平方因数 \\ (-1)^k\ ,k为n的本质不同质因子个数 \end{cases} \]

\(\mu\) 是积性函数。

性质

  1. \(\forall n \in N , \sum_{d|n}\mu(d) = [n=1]\)
    莫比乌斯反演中最常用的性质。
    推论:\(e(n) = \sum_{d|n}\mu(d) \Rightarrow e(n) = \sum_{d|n}\mu(d)1(\frac{n}{d}) \Rightarrow e=\mu*1\)
  2. \(\forall n \in N , \sum_{d|n}\frac{\mu(d)}{d} = \frac{\phi(n)}{n}\)

求莫比乌斯函数
由于 \(\mu\) 是积性函数,所以 \(\mu\) 可以像素数一样筛出来。
下面给出线性筛法:

void init(){
    memset(is_prime,1,sizeof is_prime);
    is_prime[1]=0; mu[1]=1;
    for (int i=2;i<=MAXN;i++){ //这里的MAXN注意边界
        if (is_prime[i]){
            prime[++cnt]=i;
            mu[i]=-1;
        }
        for (int j=1;j<=cnt&&1ll*i*prime[j]<=MAXN;j++){
            is_prime[i*prime[j]]=0;
            if (i%prime[j]==0) break; // mu在这个位置上本来就是0,不用额外赋值
            mu[i*prime[j]]=-mu[i]; // 质因子数+1,mu乘上-1
        }
    }
    return;
}

莫比乌斯反演

\[\textstyle g(n) = \sum_{d|n}f(d) \;\Leftrightarrow\; f(n) = \sum_{d|n}g(d)\mu(\frac{n}{d}) \]

证明
由性质一我们已知 \(e=\mu*1\)
\(g(n) = \sum_{d|n}f(d) \;\Rightarrow\; g(n) = \sum_{d|n}f(d)1(\frac{n}{d}) \;\Rightarrow\; g=f*1\)
将等式两边同乘 \(\mu\)\(g*\mu=f*(1*\mu) \;\Rightarrow\; g*\mu=f*e \;\Rightarrow\; f=g*\mu\)
于是 \(g(n) = \sum_{d|n}f(d) \;\Rightarrow\; f(n) = \sum_{d|n}g(d)\mu(\frac{n}{d})\) ,反之亦然。

例题(莫比乌斯函数及性质)

P3455 [POI2007] ZAP-Queries

给出 \(a,b,d\),求满足 \(1 \leq x \leq a\)\(1 \leq y \leq b\),且 \(\gcd(x,y)=d\) 的二元组 \((x,y)\) 的数量。
DATA:\(1 \leq n \leq 5 \times 10^4\)\(1 \leq d \leq a,b \leq 5 \times 10^4\)
Solution
答案可记作 \(Ans = \sum\limits_{i=1}^{a}\sum\limits_{j=1}^{b}[\gcd(x,y)=d]\)\(a\leq b\)
\(\because \gcd(\alpha,\beta)=1 \;\Rightarrow\; \gcd(\alpha c,\beta c)=c\)
\( \begin{aligned} \therefore Ans &= \textstyle\sum\limits_{i=1}^{\lfloor\frac{a}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{b}{d}\rfloor}[\gcd(x,y)=1]\\ &= \textstyle\sum\limits_{i=1}^{\lfloor\frac{a}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{b}{d}\rfloor}\sum_{d'|\gcd(x,y)}\mu(d') (性质一)\\ &= \textstyle\sum\limits_{d'=1}^{\lfloor\frac{a}{d}\rfloor}\mu(d')\lfloor\frac{\lfloor\frac{a}{d}\rfloor}{d'}\rfloor\lfloor\frac{\lfloor\frac{b}{d}\rfloor}{d'}\rfloor (枚举d',交换求和顺序) \end{aligned} \)
由此复杂度可降至 \(O(na)\) ,但依旧不足以通过此题。
考虑数论分块,也就是把 \(\lfloor\frac{\lfloor\frac{a}{d}\rfloor}{d'}\rfloor\lfloor\frac{\lfloor\frac{b}{d}\rfloor}{d'}\rfloor\) 相同的项合并起来算,乘与 \(\sum\limits_{d'=start}^{end}\mu(d')\) 即可,这部分用前缀和。

Code
#include <bits/stdc++.h>
#define MAXN 100003
using namespace std;
int T;
int x,y,d;
int is_prime[MAXN];
int prime[MAXN]; int cnt;
int mu[MAXN];
long long sum[MAXN];
void init(){
    for (int i=1;i<=MAXN-2;i++) is_prime[i]=1;
    is_prime[1]=0; is_prime[2]=1; mu[1]=1;
    for (int i=2;i<=MAXN-2;i++){ // 数据范围不大,这里是nlogn筛
        if (!is_prime[i]) continue;
        mu[i]=-1;
        int j=2;
        while (1ll*i*j<=MAXN-2){
            is_prime[i*j]=0;
            if (j%i==0) mu[i*j]=0;
            else mu[i*j]=mu[i]*mu[j];
            j++;
        }
    }
    for (int i=1;i<=MAXN-2;i++) if (is_prime[i]) prime[++cnt]=i;
    for (int i=1;i<=MAXN-2;i++) sum[i]=sum[i-1]+mu[i];
    return;
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    init();
    cin>>T;
    while (T--){
        cin>>x>>y>>d;
        int N=x/d,M=y/d;
        long long ans=0;
        for (int d2=1;d2<=min(N,M);d2++){
            int nxt=min(N/(N/d2),M/(M/d2));
            ans+=1ll*(sum[nxt]-sum[d2-1])*(N/d2)*(M/d2);
            d2=nxt;
        }
        cout<<ans<<'\n';
    }
    return 0;
}

P2522 [HAOI2011] Problem b

对于给出的 \(n\) 个询问,每次求有多少个数对 \((x,y)\),满足 \(a \le x \le b\)\(c \le y \le d\),且 \(\gcd(x,y) = k\)\(\gcd(x,y)\) 函数为 \(x\)\(y\) 的最大公约数。
DATA:\(1 \le n,k \le 5 \times 10^4\)\(1 \le a \le b \le 5 \times 10^4\)\(1 \le c \le d \le 5 \times 10^4\)
Solution
与上题相似,加一个容斥即可。

Code
#include <bits/stdc++.h>
#define MAXN 100003
using namespace std;
int T;
int a,b,c,d,k;
int is_prime[MAXN];
int prime[MAXN]; int cnt;
int mu[MAXN];
long long sum[MAXN];
void init(){
    for (int i=1;i<=MAXN-2;i++) is_prime[i]=1;
    is_prime[1]=0; is_prime[2]=1; mu[1]=1;
    for (int i=2;i<=MAXN-2;i++){ //数据范围小我就不用线性筛
        if (!is_prime[i]) continue;
        mu[i]=-1;
        int j=2;
        while (1ll*i*j<=MAXN-2){
            is_prime[i*j]=0;
            if (j%i==0) mu[i*j]=0;
            else mu[i*j]=mu[i]*mu[j];
            j++;
        }
    }
    for (int i=1;i<=MAXN-2;i++) if (is_prime[i]) prime[++cnt]=i;
    for (int i=1;i<=MAXN-2;i++) sum[i]=sum[i-1]+mu[i];
    return;
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    init();
    cin>>T;
    while (T--){
        cin>>a>>b>>c>>d>>k;
        int N=b/k,M=d/k;
        long long ans1=0,ans2=0,ans3=0,ans4=0;
        for (int d2=1;d2<=min(N,M);d2++){
            int nxt=min(N/(N/d2),M/(M/d2));
            ans1+=1ll*(sum[nxt]-sum[d2-1])*(N/d2)*(M/d2);
            d2=nxt;
        }
        N=(a-1)/k; M=d/k;
        for (int d2=1;d2<=min(N,M);d2++){
            int nxt=min(N/(N/d2),M/(M/d2));
            ans2+=1ll*(sum[nxt]-sum[d2-1])*(N/d2)*(M/d2);
            d2=nxt;
        }
        N=(c-1)/k; M=b/k;
        for (int d2=1;d2<=min(N,M);d2++){
            int nxt=min(N/(N/d2),M/(M/d2));
            ans3+=1ll*(sum[nxt]-sum[d2-1])*(N/d2)*(M/d2);
            d2=nxt;
        }
        N=(a-1)/k; M=(c-1)/k;
        for (int d2=1;d2<=min(N,M);d2++){
            int nxt=min(N/(N/d2),M/(M/d2));
            ans4+=1ll*(sum[nxt]-sum[d2-1])*(N/d2)*(M/d2);
            d2=nxt;
        }
        cout<<ans1-ans2-ans3+ans4<<'\n';
    }
    return 0;
}

P2257 YY的GCD

给定 \(N, M\),求 \(1 \leq x \leq N\)\(1 \leq y \leq M\)\(\gcd(x, y)\) 为质数的 \((x, y)\) 有多少对。
DATA:\(T = 10^4\)\(N, M \leq 10^7\)
Solution
只需要稍微退推一下柿子(,
\(N \leq M\)
\( \begin{aligned} Ans &= \textstyle\sum\limits_{p \in prime}^{N}\sum\limits_{i=1}^{N}\sum\limits_{j=1}^{M}[\gcd(i,j)=p]\\ &= \textstyle\sum\limits_{p \in prime}^{N}\sum\limits_{i=1}^{\lfloor\frac{N}{p}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{M}{p}\rfloor}[\gcd(i,j)=1] \\ &= \textstyle\sum\limits_{p \in prime}^{N}\sum\limits_{i=1}^{\lfloor\frac{N}{p}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{M}{p}\rfloor}\sum_{d|\gcd(i,j)}\mu(d) \\ &= \textstyle\sum\limits_{p \in prime}^{N}\sum\limits_{d=1}^{\lfloor\frac{N}{p}\rfloor}\mu(d)*\lfloor\frac{N}{pd}\rfloor*\lfloor\frac{M}{pd}\rfloor \\ \end{aligned} \)
\(T=pd\)\(d=\frac{T}{p}\)
\( \begin{aligned} Ans &= \textstyle\sum\limits_{p \in prime}^{N}\sum\limits_{d=1}^{\lfloor\frac{N}{p}\rfloor}\mu(\frac{T}{p})*\lfloor\frac{N}{T}\rfloor*\lfloor\frac{M}{T}\rfloor \\ &= \textstyle\sum\limits_{T=1}^{N}\lfloor\frac{N}{T}\rfloor\lfloor\frac{M}{T}\rfloor\sum\limits_{p|T,p \in prime}\mu(\frac{T}{p}) (枚举T,交换求和顺序) \\ \end{aligned} \)
这下前面一部分可以用数论分块做,后半部分枚举 \(p\) 计算对 \(T\) 的贡献即可。
时间复杂度 \(O(n+T\sqrt{n})\)

Code
#include <bits/stdc++.h>
#define MAXN 10000003
using namespace std;
int T;
int n,m;
int is_prime[MAXN],prime[MAXN],cnt;
int mu[MAXN],sum[MAXN];
long long f[MAXN],sumf[MAXN];
void init(){
    for (int i=2;i<=MAXN-2;i++) is_prime[i]=1;
    mu[1]=1;
    for (int i=2;i<=MAXN-2;i++){ //nlogn筛似了,换成线性筛
        if (is_prime[i]){
            prime[++cnt]=i;
            mu[i]=-1;
        }
        for (int j=1;j<=cnt&&1ll*i*prime[j]<=MAXN-2;j++){
            is_prime[i*prime[j]]=0;
            if (i%prime[j]==0) break;
            mu[i*prime[j]]=-mu[i];
        }
    }
    for (int i=1;i<=MAXN-2;i++) sum[i]=sum[i-1]+mu[i];
    for (int i=1;i<=cnt;i++){
        for (int j=1;j<=MAXN-2&&1ll*prime[i]*j<=MAXN-2;j++){ //计算质数p对T的贡献
            f[prime[i]*j]+=mu[j];
        }
    }
    for (int i=1;i<=MAXN-2;i++) sumf[i]=sumf[i-1]+f[i];
    return;
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    init();
    cin>>T;
    while (T--){
        cin>>n>>m;
        if (n>m) swap(n,m);
        long long ans=0;
        for (int T=1;T<=n;T++){
            int nxt=min(n/(n/T),m/(m/T));
            ans+=1ll*(n/T)*(m/T)*(sumf[nxt]-sumf[T-1]);
            T=nxt;
        }
        cout<<ans<<'\n';
    }
    return 0;
}

P3327 [SDOI2015] 约数个数和

\(d(x)\)\(x\) 的约数个数,给定 \(n,m\),求

\[\sum_{i=1}^n\sum_{j=1}^md(ij) \]

DATA:\(1\le T,n,m \le 50000\)
Solution
首先你需要知道一个等式:

\[d(ij)=\sum_{x|i}\sum_{y|j}[\gcd(x,y)=1] \]

证明:
记符合 \(x|i\)\(x\) 的个数为 \(g(i)\)\(y|j\) 同理, 那么后面的 \(\sum\) 一共会有 \(g(i)g(j)\) 种方案。
考虑 \([\gcd(x,y)=1]\) 的去重作用:
首先,有 \(\forall n\) 可以质因数分解为 \(p_1^{e_1}p_2^{e_2}p_3^{e_3}...\) ,那么 \(n\) 将会有 \((e_1+1)(e_2+1)(e_3+1)...\) 种本质不同的因数。
考虑对于每个 \(p\) ,设 \(i\) 中有 \(a\)\(p\)\(j\) 中有 \(b\)\(p\) ,那么 \(ij\) 的因数中 \(p\) 的次数可以是 \([0,a+b+1]\)
于是我们可以利用 \([\gcd(x,y)=1]\) 将方案数去重到 \(a+b+1\) 个。
现在来解释 \([\gcd(x,y)=1]\) 的组合意义:
要使 \(\gcd(x,y)=1\) ,显然选出来的 \(a\)\(b\) 至少有其一为 \(0\) ,分如下情况:

\[\begin{cases} a \ne 0, b = 0 \\ a = 0, b \ne 0 \\ a = 0, b = 0 \\ \end{cases} \]

那么我们发现 \(\gcd(x,y)=1\) 约束下恰好有 \(a+b+1\) 种方案,保证了不重不漏,接下来我们只需要将单个 \(p\) 的利用乘法原理情况推广到所有 \(p_i\) 即可。
至此等式成立。

例题(真正的莫比乌斯反演)

P5518 [MtOI2019] 幽灵乐团 / 莫比乌斯反演基础练习题

\[\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}\left(\frac{\text{lcm}(i,j)}{\gcd(i,k)}\right)^{f(type)} (mod\ p) \]

\[\begin{aligned} f(0)&=1 \cr f(1)&=i \times j \times k \cr f(2)&=\gcd(i,j,k) \end{aligned}\]

DATA:$$ 1\leq A,B,C\leq 10^5 \ \ \ \ 10^7 \leq p \leq 1.05\times 10^9\ \ \ \ p\in { prime} \ \ \ \ T =70$$

其它东西

题单

莫比乌斯反演(函数)练习题单

参考资料

【数论】莫比乌斯函数/莫比乌斯反演
数论小白入门-- 莫比乌斯反演
【数论】莫比乌斯函数及其反演
莫比乌斯函数
关于n,欧拉函数与莫比乌斯函数的互化

posted @   EcapsXD  阅读(30)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示