【学习笔记】莫比乌斯反演
前言/声明
首先,本人的数论水平极低,目前莫反只是刚刚入门的水平,此博客的主要作用是用于记录本人的学习过程,真的想要深入了解莫反的话这边推荐 cmd 大佬的博客(点这里),应该对你有更大帮助。
建议学习的时候能多理解些就多去理解,少硬记些结论,这样更不容易忘记。
前置知识:最基础的数论。
0 基本定义与符号
- 整除:对于任意两个整数
,如果有 ,则称 整除 ,记作 。 - 最大公约数:对于任意两个整数
,称 是 的最大公约数当且仅当 是能整除 的最大整数,记作 ,或简记为 。 - 艾弗森括号:
表示的是,如果中括号内的东西为真,则值为 ,否则为 。比如: 。 - 欧拉函数:对于正整数
,欧拉函数表示 内与 互质的正整数的个数,记作 。
1 数论函数与狄利克雷卷积
1.1 数论函数
定义:定义域为正整数(陪域为复数)的函数。
如果下文中没有特殊说明,所有提到的函数都是数论函数,所有提到的数也均为整数。
1.1.1 积性函数#
定义:如果数论函数
就比如大家应该很熟悉的欧拉函数
1.1.2 完全积性函数#
定义:如果数论函数
下面,为大家介绍几个下文会经常用到的完全积性函数:
- 恒等函数
,对于所有正整数 ,都有 ,经常作为废话出现。 - 元函数
,对于所有正整数 , ,即当且仅当 时值为 ,否则为 ,是狄利克雷卷积的单位元(下文会提到)。 - 单位函数
,对于所有正整数 , 。 - 幂函数
,对于所有正整数 , ,单位函数是幂函数的特殊情况。
显然,完全积性函数
1.2 狄利克雷卷积
定义:设
可以理解为对数论函数定义的一种运算。
比如,
狄利克雷卷积满足以下运算律:
- 交换律:
。 - 结合律:
。 - 分配律:
,这里数论函数的加法定义为点值相加,即 。
比较显然,直接把式子套上去就能证明,具体过程这里不再给出。
对于任意数论函数
证明:
对于任意数论函数
1.3 相关性质
-
对于一个积性函数
,一定有 。证明:由积性函数定义,得
,所以 。 -
对于一个积性函数
, ,其中 和 分别对应 质因数分解后的每个质因子及其对应次数。证明:
显然互质,由积性函数定义可得上式。 -
两个积性函数的狄利克雷卷积仍是积性函数。
证明:设
是两个积性函数, 是两个互质的正整数,它们的狄利克雷卷积为 。考虑合并求和符号,改为枚举
, 右边的部分显然可以根据积性函数性质合并:原命题得证。
2 莫比乌斯函数
了解了上面的前置知识之后,我们就可以逐步引出主角莫比乌斯函数了。
2.1 来源
假设现在有两个单变量函数
如果
不过现在又有一个新的问题,如果易求的函数是
我们考虑将上面的式子变为狄利克雷卷积的形式:
两边同时乘上
那么如果我们能够求出
而这个
但是新的问题又来了,
2.2 定义
首先,
而一个积性函数的逆其实是可以构造出来的,具体构造的方法:点这里查看。
因为比较复杂(其实是我不会),具体过程这里不再具体给出。
莫比乌斯函数的定义如下:
- 若
,则 。 - 若
, 是互不相同的质数,那么 。 - 否则
。
显然,
2.3 相关性质
-
对于任意的正整数
,总是有:显然,因为
,而上式等价于 。下面给出具体证明过程:-
当
时显然成立。 -
当
时,对 进行质因子分解得 。在 的所有因子当中,当且仅当其所有质因子次数都是 时 值才不为 ,而含有 个不同质因子的因子有 个,那么显然有:根据二项式定理
,令 ,代入可得原式为 。
-
-
对于任意的正整数
,总是有:上式等价于
,证明涉及较复杂的容斥,不具体展开。
2.4 程序求解
-
质因数分解暴力求解,直接根据定义即可,单次复杂度
。 -
根据积性函数性质,线性筛预处理,总复杂度
。void init(int n){ memset(isPrime,1,sizeof(isPrime)); isPrime[1]=0;mu[1]=1; For(i,2,n){ if(isPrime[i]) pri[++cnt]=i,mu[i]=-1; For(j,1,cnt){ if(i*pri[j]>n) break; isPrime[i*pri[j]]=0; mu[i*pri[j]]=(i%pri[j]==0)?0:-mu[i]; if(i%pri[j]==0) break; } } }
3 莫比乌斯反演公式
-
公式一:
证明:显然
,由 ,用 替换掉 可得上式。 -
公式二:
证明:见上文 2.1 部分,不再重复。
-
公式三:
限于本人水平,不证。
4 例题
目前准备了三四道,但都是十分基础的那种入门题,有空立马来写。。。
4.1 公式一的应用
公式一是最好掌握,但也是最需要掌握的内容,下面我们来几道题实战一下。
【例题一】互质数对#
题目大意:
其中
题目分析:考虑用公式一来替换
考虑一个经典结论:
再接下来,我们再使用一个经典套路——交换枚举顺序,观察交换后的新限制。
考虑如果我们先枚举
考虑
如果我们用线性筛预处理
但是很显然
如果你不会整除分块,点这里。
int T,n,m,cnt,pri[N],mu[N],sm[N];
bool isPrime[N];
void init(int n){ //预处理 mu
memset(isPrime,1,sizeof(isPrime));
isPrime[1]=0;mu[1]=-1;
For(i,2,n){
if(isPrime[i]) pri[++cnt]=i,mu[i]=1;
For(j,1,cnt){
if(i*pri[j]>n) break;
isPrime[i*pri[j]]=0;
mu[i*pri[j]]=(i%pri[j]==0)?0:-mu[i];
if(i%pri[j]==0) break;
}
}
For(i,1,n) sm[i]=sm[i-1]+mu[i]; //对 mu 前缀和
}
ll calc(int n,int m){ //整除分块
ll ans=0;
for(int l=1,r=0;l<=min(n,m);l=r+1){
r=min(n/(n/l),m/(m/l));
ans+=1ll*(n/l)*(m/l)*(sm[r]-sm[l-1]); //计算答案
}
return ans;
}
void Main(){
init(1e5);read(T);
while(T--){
read(n,m);
printf("%lld\n",calc(n,m));
}
}
【例题二】 求和#
题目大意:给定你
其中
题目分析:我们可以试着继续整出来上题中那种
首先,我们考虑去枚举
经典结论:
考虑故技重施,再用上一题的方法进行变形:
分析下此时的复杂度,后面那个
蛇皮操作之——改变枚举量,令
由
显然可以线性筛出
ll n,cnt,pri[N],phi[N],s[N];
bool isPrime[N];
void init(int n){
memset(isPrime,1,sizeof(isPrime));
isPrime[1]=0;phi[1]=1;
For(i,2,n){
if(isPrime[i]) pri[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt&&i*pri[j]<=n;j++){
isPrime[i*pri[j]]=0;
if(!(i%pri[j])){
phi[i*pri[j]]=phi[i]*pri[j];
break;
}
phi[i*pri[j]]=phi[i]*phi[pri[j]];
}
}
For(i,1,n) s[i]=s[i-1]+phi[i];
}
ll calc(int n){
ll res=0,r;
for(int l=1;l<=n;l=r+1){
r=n/(n/l);
res+=(s[r]-s[l-1])*(n/l)*(n/l);
}
return res;
}
void Main(){
read(n);init(n);
printf("%lld",calc(n));
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现