Note -「Mobius 反演」光速入门
UPD:修改了 Euler 筛法代码框架。
若无特别说明,\(x,y\) 等形式变量均 \(\in\mathbb N_+\);\(p\) 为素数。
Preface
数论函数
我们称任意 \(f:\mathbb N_+\rightarrow\mathbb C\) 为一个数论函数。
积性函数
对于两个数论函数 \(f\),若对于任意 \(x\perp y\)(即 \(x,y\) 互素,或说 \(\gcd(x,y)=1\)),都有 \(f(x)\cdot f(y)=f(xy)\),那么称此数论函数是积性函数,且显然有 \(f(1)=1\)。
可以发现,在此定义下,我们只需要知道该函数在素数幂(\(p^c~(c\in\mathbb N_+)\))处的点值,就能还原整个函数。
特别地,若任意 \(x,y\) 都有 \(f(x)\cdot f(y)=f(xy)\),那么称此数论函数是完全积性函数。例如,\(I(n)=1\) 是一个常函数,自然可以得到它是一个完全积性函数。
重要的一点是,绝大部分积性函数可以在 Euler 筛法的框架下快速求出所有点值。
积性在一些函数运算中得以延续。设 \(f,g\) 为积性函数,\(k\in\mathbb N_+\),则:
- \(h(n)=(f(n))^k\) 积性(不写作 \(f^k(n)\) 是为区别 Dirichlet 卷积);
- \(h(n)=f(n^k)\) 积性;
- \(h(n)=f(n)\cdot g(n)\) 积性;
- \(h(n)=(f\star g)(n)\) 积性,后文详解。
Dirichlet 卷积
卷积是什么呢?对于任意三个函数 \(f,g,h\),若有:
\]
则 \(h\) 是 \(f\) 和 \(g\) 的 \(\oplus\) 卷积。例如 \(\oplus\) 为加号,则 \(h\) 是 \(f\) 和 \(g\) 的普通卷积;若 \(\oplus\) 为异或,则 \(h\) 是 \(f\) 和 \(g\) 的异或卷积。
而当 \(\oplus\) 为乘号,\(f,g,h\) 为数论函数,有
\]
此时 \(h\) 即为 \(f\) 和 \(g\) Dirichlet 卷积的结果。记为
\]
当然,另一种表达方式为
\]
Dirichlet 卷积有以下性质:
- 交换律:\(f\star g=g\star f\);
- 结合律:\((f\star g)\star h=f\star(g\star h)\);
- 分配律:\(f\star(g+h)=f\star g+f\star h\)。
带入可证,此处略过。
Dirichlet 卷积还有一个重要性质:若 \(f,g\) 积性,则 \(h=f\star g\) 积性。
证明:对于任意 \(x\perp y\):
h(x)h(y)&=\left(\sum_{d_x|x}f(d_x)g(\frac{x}{d_x})\right)\left(\sum_{d_y|y}f(d_y)g(\frac{y}{d_y}) \right)\\
&=\sum_{d_x|x}\sum_{d_y|y}f(d_x)f(d_y)g(\frac{x}{d_x})g(\frac{y}{d_y})\\
&=\sum_{d_x|x}\sum_{d_y|y}f(d_xd_y)g(\frac{xy}{d_xd_y})\\
&=\sum_{d|xy}f(d)g(\frac{xy}d)\\
&=h(xy)
\end{aligned}
\]
Dirichlet 卷积中的特殊函数
Dirichlet 卷积既然已是一种函数间的运算,我们就有必要研究一些特殊的“运算值”。例如零元,幺元等。一些常用的函数如下:
- \(I(n)=1\),常数函数;
- \(\epsilon(n)=[n=1]\),单位函数,Dirichlet 卷积的(左、右)幺元;
- \(\operatorname{id}(n)=n\),恒等函数。
这三者看似无用,但它们之间的运算可以表达出常见的数论函数:
\(\varphi(n)\),欧拉函数;
\(\sigma_0(n)\),约数个数函数;
……
突然,Mobius 就提出一个问题:\(I\) 在 Dirichlet 卷积下的逆元是什么?
Mobius 函数 & Mobius 反演
Mobius 函数 \(\mu\)
逆元?两数相乘为 \(1\) 是乘法逆元,类似地,两函数相卷得到幺元 \(\epsilon\),则两函数互为卷积逆元。Mobius 函数实际上就是一个构造出的 \(I\) 的逆元,记作 \(\mu\)。
\(\mu\) 是一个积性函数,定义式为:
1&n=1\\
(-1)^k&n=p_1p_2\cdots p_k,~~~~p\text{ 为两两不同的素数}\\
0&\text{otherwise}
\end{cases}
\]
这样看着很臃肿。注意 \(\mu\) 是一个积性函数,我们只需要描述起在 \(p^c~(c\in\mathbb N_+)\) 处的点值。可以看出:
\]
\(\mu\) 函数是为了满足下式:
\]
即:
\]
证明:\(n=1\) 时显然成立,仅需证明 \(n>1\) 时左式恒为 \(0\)。设 \(n=\prod p_i^{\alpha_i}\),显然仅需考虑左式中 \(d=\prod p_i\) 时的和。不妨设 \(n\) 含有素因子的集合为 \(P\),则左式有:
\sum_{d|n}\mu(d)&=\sum_{S\subseteq P}\mu(\prod_{p\in S}p)\\
&=\sum_{S\subseteq P}(-1)^{|S|}\\
&=\sum_{|S|\in[0,|P|]}\binom{|P|}{|S|}(-1)^{|S|}\\
&=(1-1)^{|P|}\\
&=0^{|P|}~~~~(|P|>0)\\
&=0
\end{aligned}
\]
在此后的推导中,我们通常仅把 \(\mu\) 看做“\(I\) 的逆元”而不考虑其内部表达式,故多数情况不需要如此考虑其展开后的运算。
Mobius 反演
充分认识 \(\mu\) 之后,反演公式其实非常浅显。对于两个数论函数 \(f,g\),满足:
\]
证明:左式左右同时卷 \(\mu\) 即证 \(\Rightarrow\);右式左右同时卷 \(I\) 即证 \(\Leftarrow\)。
还有两种和式形式:
\]
\]
\((1)\) 即为卷积形式,已证,下证 \((2)\)。
证明,仅证 \(\Rightarrow\),倒推结论:
\sum_{n|d}f(d)\mu(\frac{d}n)&=\sum_{k=1}^{+\infty}f(kn)\mu(k)\\
&=\sum_{k=1}^{+\infty}\mu(k)\sum_{kn|d}f(d)\\
&=\sum_{n|d}g(d)\sum_{k|\frac{n}d}\mu(k)\\
&=\sum_{n|d}g(d)\epsilon(\frac{n}d)\\
&=g(n)
\end{aligned}
\]
基础应用
我们来推导几个常见的函数或式子。
约数个数 \(\sigma_0\)
定义式:\(\sigma_0(n)=\sum_{d|n}1\)。
\sigma_0(n)&=\sum_{d|n}1\\
&=\sum_{d|n}I(d)I(\frac{n}d)\\
&=I^2(n)
\end{aligned}
\]
结论:
\]
欧拉函数 \(\varphi\)
定义式:\(\varphi(n)=\sum_{i=1}^n[i\perp n]\)。
\varphi(n)&=\sum_{i=1}^n[i\perp n]\\
&=\sum_{i=1}^n\sum_{d|i\land d|n}\mu(d)~~~~*\\
&=\sum_{d|n}\mu(d)\frac{n}d\\
&=\sum_{d|n}\mu(d)\operatorname{id}(\frac{n}d)\\
&=(\mu\star\operatorname{id})(n)
\end{aligned}
\]
标注 \(*\) 的步骤运用了 Mobius 反演,下文亦如此。结论:
\]
反演魔法
例一
类似题目 Link.
给定 \(n,m,k\),求
\]
传说中的七倍经验题。直接来叭:
\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=k]&=\sum_{i=1}^{\lfloor\frac{n}k\rfloor}\sum_{j=1}^{\lfloor\frac{m}k\rfloor}[i\perp j]\\
&=\sum_{i=1}^{\lfloor\frac{n}k\rfloor}\sum_{j=1}^{\lfloor\frac{m}k\rfloor}\sum_{d|i\land d|j}\mu(d)~~~~*\\
&=\sum_{d=1}^{\min\{\lfloor\frac{n}k\rfloor,\lfloor\frac{m}k\rfloor\}}\mu(d)\lfloor\frac{n}{kd}\rfloor\lfloor\frac{m}{kd}\rfloor
\end{aligned}
\]
\(\mathcal O(n)\) 预处理后整除分块即可 \(\mathcal O(\sqrt n)\) 求解。整除分块是莫反题中高频出现的 trick,一定要用熟。
例二
给定 \(T\) 组 \(n,m\),对于每组,求
\]
\(T\le10^4\),\(n,m\le10^7\)。
式子很简单,主要运用换元法
\sum_{i=1}^n\sum_{j=1}^m\operatorname{lcm}(i,j)&=\sum_{d=1}^nd\sum_{i=1}^{\lfloor\frac{n}d\rfloor}\sum_{i=1}^{\lfloor\frac{m}d\rfloor}ij[i\perp j]\\
&=\sum_{d=1}^nd\sum_{d'=1}^{\lfloor\frac{n}{d}\rfloor}S(\lfloor\frac{n}{dd'}\rfloor)S(\lfloor\frac{m}{dd'}\rfloor)d'^2~~~~\text{let }S(n)=\frac{n(n+1)}2\\
&=\sum_{T=1}^nS(\lfloor\frac{n}T\rfloor)S(\lfloor\frac{m}T\rfloor)T\sum_{d|T}d\mu(d)~~~~\text{let } T=dd'~~~~*
\end{aligned}
\]
再令 \(f(n)=n\sum_{d|n}d\mu(d)\),由于化简不来,我们转而证明它积性可直接筛,具体可见下文「线性筛 trick」。
最终 \(\mathcal O(n)-\mathcal O(\sqrt n)\) 解决。
例三
令 \(\sigma(n)\) 为 \(n\) 的约数之和。给出 \(T\) 个 \(n\),对于每个 \(n\),求
\]
\(T\le5\times10^4\),\(n\le10^6\)。
只要睡醒了应该是有把 \(\max\) 拆开的意识的。原式化为
\]
\(\sigma(i^2)\) 可证积性,直接筛出后一项。对于前一项,我们先来研究 \(\sigma(ij)\) 的性质:
引理:
\]
证明:对于每个 \(d|ij\),当且仅当 \(y=\gcd(d,j),~x=\frac{d}y\) 时被统计一次。考虑一个 \(a|d\land a|i\land a|j\),一定有 \(a\not|x\),不然就不可能有 \(x\perp \frac{j}y\),所以以上表述成立。
利用引理,记 \(f(n)=n\sum_{i=1}^n\sigma(ni)\),推导:
f(n)&=n\sum_{i=1}^n\sum_{x|n}\sum_{y|i}xy[x\perp\frac{i}y]\\
&=n\sum_{i=1}^n\sum_{x|n}\sum_{y|i}xy\sum_{d|x\land d|\frac{i}y}\mu(d)~~~~*\\
&=n\sum_{i=1}^n\sum_{d|n\land d|i}\mu(d)\sum_{x|n\land d|x}\sum_{y|i\land d|y}\frac{ix}y\\
&=n\sum_{i=1}^n\sum_{d|n\land d|i}\mu(d)\sum_{x|\frac{n}d}\sum_{y|\frac{i}d}\frac{ix}y,~~~~x,y\mbox{ 同时约掉 } d\\
&=n\sum_{i=1}^n\sum_{d|n\land d|i}\mu(d)\sigma(\frac{n}d)\sum_{y|\frac{i}d}\frac{i}y\\
&=n\sum_{i=1}^n\sum_{d|n\land d|i}\mu(d)\sigma(\frac{n}d)d\sum_{y|\frac{i}d}\frac{\frac{i}y}d\\
&=n\sum_{i=1}^n\sum_{d|n\land d|i}d\mu(d)\sigma(\frac{n}d)\sigma(\frac{i}d)\\
&=n\sum_{d|n}d\mu(d)\sigma(\frac{n}d)\sum_{i=1}^\frac{n}{d}\sigma(i)
\end{aligned}
\]
筛出 \(\mu,\sigma\),枚举 \(d\) 和 \(\frac{n}d\),可以 \(\mathcal O(n\ln n)\) 算出所有 \(f\),具体可见下文「\(\mathcal O(n\ln n)\) 刷表 trick」以及我的题解。
最终,\(\mathcal O(n\ln n)-\mathcal O(1)\) 解决问题。
魔法中的 tricks
毕竟 Mobius 反演不能把所有式子化成一眼能求。当我们在推导过程中卡住的时候,可以尝试用一些 trick “暴力”计算得到的式子,说不定就是正解呢!
线性筛 trick
记住一句话:积性函数都能筛。
Euler 筛法的框架如下:
inline void sieve ( const int n ) {
/* 初始化函数在 1 处的点值(=1) */
for ( int i = 2; i <= n; ++i ) {
if ( !vis[i] ) {
pr[++pn] = i];
/* 计算函数在素数处的点值 */
}
for ( int j = 1, t; ( t = i * pr[j] ) <= n; ++j ) {
vis[t] = true;
/* 注意:pr[j] 一定是 t 的最小素因子 */
if ( i % pr[j] ) {
/* pr[j] \not| i,利用积性处理 t 处点值 */
} else {
/* pr[j] | i,特殊处理 t 处点值 */
break;
}
}
}
}
难点只有两个:
- 如何判断某个函数是积性函数?
- 如何处理计算的 \(t\) 处点值?
对于前者,打表(迫真)和带入计算都是不错的选择。后者则需要根据函数表达式灵活处理,一般来说都是加减乘除能够解决的,某些情况(例如筛 \(\sigma_1\))需要额外记录信息。
筛 \(\sigma_1\)
\(\sigma_1\) 也简记作 \(\sigma\),有定义
\]
则任意一对 \(x\perp y\),带入
\sigma(x)\sigma(y)&=\sum_{d_x|x}d_x\sum_{d_y|y}d_y\\
&=\sum_{d_x|x,d_y|y}d_xd_y\\
&=\sum_{d|xy}d\\
&=\sigma(xy)
\end{aligned}
\]
第三步用了 \(x\perp y\) 的条件。可见 \(\sigma\) 积性,考虑如何筛。
小奥教会我们,对于 \(n=\prod p_i^{\alpha_i}\)(标准分解形式),有
\]
证略。我们来处理筛法中的特殊情况,设 \(p=p_k\) 为 \(x\) 的最小素因子,则应有 \(p^2|x\)。观察:
\sigma(x)=\left(\prod_{p_i\not=p}\sum_{j=0}^{\alpha_i}p_i^j\right)\left(\sum_{j=0}^{\alpha_k+1}p^j\right)
\]
乘积式很难直接修改某一项的值,所以我们需要对于每个 \(x\),记录其最小素因子的贡献,记作 \(\sigma_p(x)\),有
\]
\(\sigma_p\) 很显然可以在筛法中处理。此后,就能得到
\]
问题解决。值得再次强调的是,Euler 筛法中的合数一定被其最小素因子筛掉。
筛 \(\operatorname{id}^k\mu\)
即 洛谷 P4449 的阶段性问题。
做题的时候,经常遇见此类很多个基础的积性函数卷起来的函数,它们亦可被线性筛。
同样的姿势,设 \(p\) 为 \(x\) 的最小素因子,且有 \(p^2|x\),观察:
\operatorname{id}^k\mu(x)=\sum_{d|x}d^k\mu(\frac{x}d)
\]
分类讨论第二个和式中的 \(d\):
- 不含新加入的素因子 \(p\),对应了第一个和式中的每个 \(d^k\mu(\frac{x}{dp})\),只不过 \(x\) 多了一个 \(p\),所以应为 \(d^k\mu(\frac{x}d)\)。由于 \(p^2|x\),且 \(d|\frac{x}p\Rightarrow p|\frac{x}d\),故 \(\mu(x)=\mu(\frac{x}d)=0\),无贡献;
- 含有新加入的素因子 \(p\),亦对应第一个和式中的每个 \(d^k\mu(\frac{x}{dp})\),只不过 \(d\) 多了一个 \(p\),所以应为 \(d^kp^k\mu(\frac{x}{dp})\)。
综上:
\]
筛 \(f(n)=n\sum_{d|n}d\mu(d)\)
这是上文的问题,我们得证明它能筛(积性),在得出它如何筛。
还是惯用手法,带入任意 \(x\perp y\):
f(x)f(y)&=\left( x\sum_{d_x|x}d_x\mu(d_x) \right)\left( y\sum_{d_y|y}d_y\mu(d_y) \right)\\
&=xy\sum_{d_x|x,d_y|y}d_xd_y\mu(d_x)\mu(d_y)\\
&=xy\sum_{d|xy}d\mu(d)\\
&=f(xy)
\end{aligned}
\]
果然积性。
当然,也可以用积性的延续性质。发现
\]
亦能说明 \(f\) 积性。
接下来,我们从积性的角度着手,思考素数幂 \(p^k\) 处的点值。边界有:
\]
对于其他 \(k>1\):
f(p^k)&=p^k\sum_{i=0}^kp^i\mu(p^i)\\
&=p^k(1-p)\\
&=pf(p^{k-1})
\end{aligned}
\]
所以在筛法中,有 \(p^2|x\),那么:
\]
简洁地结束问题。
\(\mathcal O(n\ln n)\) 刷表 trick
基于 \(\sum_{i=1}^n\frac{n}i=\mathcal O(n\ln n)\),很多时候可以把 Dirichlet 卷积形式的函数暴力打表出来。框架如下:
for ( int i = 1; i <= MAXN; ++i ) {
for ( int j = 1, t; ( t = i * j ) <= MAXN; ++j ) {
/* 用 i 和 j 的信息对 t=i*j 贡献 */
}
}
以前文求
\]
为例,步骤如下:
常系数剔除:\(n\) 显然最后再乘上去。
形式变化:类似变化乘法卷积的操作,把式子变化成形如 \(\sum_{d|n}A(d)B(\frac{n}d)\) 的形式。此处有
\[\frac{f(n)}n=\sum_{d|n}\left(d\mu(d)\right)\left(\sigma(\frac{n}d)\sum_{i=1}^{\frac{n}d}\sigma(i)\right)
\]预处理上述 \(A(n)\),\(B(n)\) 的值。此处即筛出 \(\mu\) 和 \(\sigma\),预处理 \(\sigma\) 前缀和。
套用框架计算。
莫得什么难点。(
Conclusion
莫反题的难点一般不是莫反。(
Practice makes perfect. 式子多推一下自然能找到感觉。建议尝试自己推导文中的式子,再对照文中的推导看看是否可以优化。(当然我可能推得很细,也可能兔子就是要蠢一点 qwq。
终于写完了 qwq!
Note -「Mobius 反演」光速入门的更多相关文章
- Note -「单位根反演」学习笔记
\(\mathcal{Preface}\) 单位根反演,顾名思义就是用单位根变换一类式子的形式.有关单位根的基本概念可见我的这篇博客. \(\mathcal{Formula}\) 单位根反演的 ...
- Note -「动态 DP」学习笔记
目录 「CF 750E」New Year and Old Subsequence 「洛谷 P4719」「模板」"动态 DP" & 动态树分治 「洛谷 P6021」洪水 「S ...
- Note -「Lagrange 插值」学习笔记
目录 问题引入 思考 Lagrange 插值法 插值过程 代码实现 实际应用 「洛谷 P4781」「模板」拉格朗日插值 「洛谷 P4463」calc 题意简述 数据规模 Solution Step 1 ...
- 「专题总结」LCT入门
上次xuefeng说我的专题总结(初探插头dp)太不适合入门了,所以这次丢一些题解包以外的东西. 关键是我自己也不会...急需梳理一下思路... (让我口胡数据结构???顺便推广一下全世界最短的lct ...
- ☆ [POI2007] ZAP-Queries 「莫比乌斯反演」
题目类型:莫比乌斯反演 传送门:>Here< 题意:求有多少对正整数对\((a,b)\),满足\(0<a<A\),\(0<b<B\),\(gcd(a,b)=d\) ...
- 「BZOJ 3529」「SDOI 2014」数表「莫比乌斯反演」
题意 有一张 \(n\times m\) 的数表,其第\(i\)行第\(j\)列的数值为能同时整除\(i\)和\(j\)的所有自然数之和. \(T\)组数据,询问对于给定的 \(n,m,a\) , 计 ...
- 「BZOJ 3994」「SDOI 2015」约数个数和「莫比乌斯反演」
题意 设\(d(x)\)为\(x\)的约数个数,求\(\sum_{i=1}^{n}\sum_{j=1}^{m}d(ij)\). 题解 首先证个公式: \[d(ij) = \sum_{x|i}\sum_ ...
- 「CF235E」Number Challenge「莫比乌斯反演」
一个结论:(从二维扩展来的,三维也是对的,证明可以考虑质因数分解) \[ d(ijk)=\sum_{i'|i}\sum_{j'|j}\sum_{k'|k}[\gcd(i',j')=1][\gcd(i' ...
- Note -「Min_25 筛」“你就说这素因子你要不要吧?你要不要?”
赛上想写,Track Lost 了属于是. \(\mathscr{Intro}\) Min_25 筛是用于求积性函数前缀和,同时顺带求出一些"有意思"的信息的筛法. 一 ...
随机推荐
- [ unittest ] 使用初体验
import unittest from cal import Calculate class Mytest(unittest.TestCase): def setUp(self): self.cal ...
- mysql 5.7.29 在centos7.6下超简单的本地yum源安装与配置
目录 生成yum源元数据 从网易镜像站下载MySQL 5.7 的 bundle包 创建文件 mysql-local.repo 执行yum install命令 生成yum源元数据 createrepo ...
- 使用 arguments 对象
arguments 对象表示参数集合,它是一个伪类数组,拥有与数组相似的结构,可以通过数组下标的形式访问函数实参值,但是没有基础 Array 的原型方法. //函数没有定义形参,但是在函数体内通过 a ...
- 使用Python 爬取 京东 ,淘宝。 商品详情页的数据。(避开了反爬虫机制)
以下是爬取京东商品详情的Python3代码,以excel存放链接的方式批量爬取.excel如下 代码如下 from selenium import webdriver from lxml import ...
- Struts-S2-045漏洞利用
最近也是在看Struts2的漏洞,这里与大家共同探讨一下,本次我复现的是s2-045这个编号的漏洞 漏洞介绍 Apache Struts 2被曝存在远程命令执行漏洞,漏洞编号S2-045,CVE编号C ...
- java计算器(简单版)
前言 之前在学习完Java的方法后,我发现自己可以开始写计算器这个"经典"的项目了,于是我花了一点时间写下了这个计算器的程序,也写下了这篇文章. 在这里,我需要说明一下,这个程序只 ...
- 记录未解决的问题:docker中无法启动mysqld
首先在docker中安装mysql server的包: sudo yum install mysql sudo yum install mariadb-server mariadb /usr/libe ...
- Windows系统安装和office版本兼容
MSDN, I tell you 下载windows10系统各种纯净镜像.但是还是推荐使用官网修改参数显示出下载链接,下载windows10最新版. 在最近几次重做系统中,PE工具似乎无法识别从MSD ...
- vue学习3-VSCode添加自定义代码片段
1. ctrl+shift+p:打开命令行窗口. 2. 搜索snippets关键字.选择Preferenece:Configure User Snippets 3. 选择html.json,打开这个文 ...
- jmeter - 阶梯式性能指标监听
概述 我们在进行阶梯式压力测试的时候,聚合报告生成的结果是一个汇总数据.并不会阶梯式的统计压测性能数据.这样我们就不能去对比不同阶梯压力下的性能数据变化趋势. 期望 假设现在一共会加载100个线程,我 ...