莫比乌斯函数及其反演
一些定义
数论函数
定义域为正整数的函数,一般分类如下:
- 积性函数
对于 \(\forall x,y \in N , gcd(x,y)=1\) ,若 \(f(x \cdot y)=f(x) \cdot f(y)\) ,则 \(f\) 是积性函数。 - 完全积性函数
对于 \(\forall x,y \in N\) ,若 \(f(x \cdot y)=f(x) \cdot f(y)\) ,则 \(f\) 是完全积性函数。 - 非积性函数
狄利克雷卷积
可以理解为数论函数的乘法,常用符号 \(*\) 表示。
若 \(f,g\) 均为数论函数,则有 \((f*g)(n) = \sum_{d|n}f(d)g(\frac{n}{d})\) 。
对于数论函数乘法,其单位元函数为 \(e\) :
即对于任意数论函数 \(f\) ,都有 \(f*e=f\) 。
狄利克雷卷积满足交换律和结合律。
莫比乌斯函数
莫比乌斯函数 \(\mu\) 的定义如下:
\(\mu\) 是积性函数。
性质:
- \(\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\) - \(\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;
}
莫比乌斯反演
证明:
由性质一我们已知 \(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\),求
DATA:\(1\le T,n,m \le 50000\)。
Solution
首先你需要知道一个等式:
证明:
记符合 \(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\) ,分如下情况:
那么我们发现 \(\gcd(x,y)=1\) 约束下恰好有 \(a+b+1\) 种方案,保证了不重不漏,接下来我们只需要将单个 \(p\) 的利用乘法原理情况推广到所有 \(p_i\) 即可。
至此等式成立。
例题(真正的莫比乌斯反演)
P5518 [MtOI2019] 幽灵乐团 / 莫比乌斯反演基础练习题
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,欧拉函数与莫比乌斯函数的互化
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 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)