UPD:修改了 Euler 筛法代码框架。
若无特别说明,x,y 等形式变量均 ∈N+;p 为素数。
Preface
数论函数
我们称任意 f:N+→C 为一个数论函数。
积性函数
对于两个数论函数 f,若对于任意 x⊥y(即 x,y 互素,或说 gcd(x,y)=1),都有 f(x)⋅f(y)=f(xy),那么称此数论函数是积性函数,且显然有 f(1)=1。
可以发现,在此定义下,我们只需要知道该函数在素数幂(pc (c∈N+))处的点值,就能还原整个函数。
特别地,若任意 x,y 都有 f(x)⋅f(y)=f(xy),那么称此数论函数是完全积性函数。例如,I(n)=1 是一个常函数,自然可以得到它是一个完全积性函数。
重要的一点是,绝大部分积性函数可以在 Euler 筛法的框架下快速求出所有点值。
积性在一些函数运算中得以延续。设 f,g 为积性函数,k∈N+,则:
- h(n)=(f(n))k 积性(不写作 fk(n) 是为区别 Dirichlet 卷积);
- h(n)=f(nk) 积性;
- h(n)=f(n)⋅g(n) 积性;
- h(n)=(f⋆g)(n) 积性,后文详解。
Dirichlet 卷积
卷积是什么呢?对于任意三个函数 f,g,h,若有:
h(k)=∑i⊕j=kf(i)⋅g(j)
则 h 是 f 和 g 的 ⊕ 卷积。例如 ⊕ 为加号,则 h 是 f 和 g 的普通卷积;若 ⊕ 为异或,则 h 是 f 和 g 的异或卷积。
而当 ⊕ 为乘号,f,g,h 为数论函数,有
h(k)=∑ij=kf(i)⋅g(j)
此时 h 即为 f 和 g Dirichlet 卷积的结果。记为
h=f⋆g
当然,另一种表达方式为
h(k)=∑i|nf(i)⋅g(ki)
Dirichlet 卷积有以下性质:
- 交换律:f⋆g=g⋆f;
- 结合律:(f⋆g)⋆h=f⋆(g⋆h);
- 分配律:f⋆(g+h)=f⋆g+f⋆h。
带入可证,此处略过。
Dirichlet 卷积还有一个重要性质:若 f,g 积性,则 h=f⋆g 积性。
证明:对于任意 x⊥y:
h(x)h(y)=⎛⎝∑dx|xf(dx)g(xdx)⎞⎠⎛⎝∑dy|yf(dy)g(ydy)⎞⎠=∑dx|x∑dy|yf(dx)f(dy)g(xdx)g(ydy)=∑dx|x∑dy|yf(dxdy)g(xydxdy)=∑d|xyf(d)g(xyd)=h(xy)
Dirichlet 卷积中的特殊函数
Dirichlet 卷积既然已是一种函数间的运算,我们就有必要研究一些特殊的“运算值”。例如零元,幺元等。一些常用的函数如下:
- I(n)=1,常数函数;
- ϵ(n)=[n=1],单位函数,Dirichlet 卷积的(左、右)幺元;
- id(n)=n,恒等函数。
这三者看似无用,但它们之间的运算可以表达出常见的数论函数:
-
φ(n),欧拉函数;
-
σ0(n),约数个数函数;
-
……
突然,Mobius 就提出一个问题:I 在 Dirichlet 卷积下的逆元是什么?
Mobius 函数 & Mobius 反演
Mobius 函数 μ
逆元?两数相乘为 1 是乘法逆元,类似地,两函数相卷得到幺元 ϵ,则两函数互为卷积逆元。Mobius 函数实际上就是一个构造出的 I 的逆元,记作 μ。
μ 是一个积性函数,定义式为:
μ(n)=⎧⎨⎩1n=1(−1)kn=p1p2⋯pk, p 为两两不同的素数0otherwise
这样看着很臃肿。注意 μ 是一个积性函数,我们只需要描述起在 pc (c∈N+) 处的点值。可以看出:
μ(pc)=[c=1](−1)
μ 函数是为了满足下式:
I⋆μ=ϵ
即:
∑d|nμ(d)=[n=1]
证明:n=1 时显然成立,仅需证明 n>1 时左式恒为 0。设 n=∏pαii,显然仅需考虑左式中 d=∏pi 时的和。不妨设 n 含有素因子的集合为 P,则左式有:
∑d|nμ(d)=∑S⊆Pμ(∏p∈Sp)=∑S⊆P(−1)|S|=∑|S|∈[0,|P|](|P||S|)(−1)|S|=(1−1)|P|=0|P| (|P|>0)=0
在此后的推导中,我们通常仅把 μ 看做“I 的逆元”而不考虑其内部表达式,故多数情况不需要如此考虑其展开后的运算。
Mobius 反演
充分认识 μ 之后,反演公式其实非常浅显。对于两个数论函数 f,g,满足:
f=g⋆I⟺g=f⋆μ
证明:左式左右同时卷 μ 即证 ⇒;右式左右同时卷 I 即证 ⇐。
还有两种和式形式:
f(n)=∑d|ng(d)⟺g(n)=∑d|nf(d)μ(nd)(1)
f(n)=∑n|dg(d)⟺g(n)=∑n|df(d)μ(dn)(2)
(1) 即为卷积形式,已证,下证 (2)。
证明,仅证 ⇒,倒推结论:
∑n|df(d)μ(dn)=+∞∑k=1f(kn)μ(k)=+∞∑k=1μ(k)∑kn|df(d)=∑n|dg(d)∑k|ndμ(k)=∑n|dg(d)ϵ(nd)=g(n)
基础应用
我们来推导几个常见的函数或式子。
约数个数 σ0
定义式:σ0(n)=∑d|n1。
σ0(n)=∑d|n1=∑d|nI(d)I(nd)=I2(n)
结论:
σ0=I2
欧拉函数 φ
定义式:φ(n)=∑ni=1[i⊥n]。
φ(n)=n∑i=1[i⊥n]=n∑i=1∑d|i∧d|nμ(d) ∗=∑d|nμ(d)nd=∑d|nμ(d)id(nd)=(μ⋆id)(n)
标注 ∗ 的步骤运用了 Mobius 反演,下文亦如此。结论:
φ=μ⋆id
反演魔法
例一
类似题目 Link.
给定 n,m,k,求
n∑i=1m∑j=1[gcd(i,j)=k]
传说中的七倍经验题。直接来叭:
n∑i=1m∑j=1[gcd(i,j)=k]=⌊nk⌋∑i=1⌊mk⌋∑j=1[i⊥j]=⌊nk⌋∑i=1⌊mk⌋∑j=1∑d|i∧d|jμ(d) ∗=min{⌊nk⌋,⌊mk⌋}∑d=1μ(d)⌊nkd⌋⌊mkd⌋
O(n) 预处理后整除分块即可 O(√n) 求解。整除分块是莫反题中高频出现的 trick,一定要用熟。
例二
BZOJ 2693.
给定 T 组 n,m,对于每组,求
n∑i=1m∑j=1lcm(i,j)mod(108+9)
T≤104,n,m≤107。
式子很简单,主要运用换元法
n∑i=1m∑j=1lcm(i,j)=n∑d=1d⌊nd⌋∑i=1⌊md⌋∑i=1ij[i⊥j]=n∑d=1d⌊nd⌋∑d′=1S(⌊ndd′⌋)S(⌊mdd′⌋)d′2 let S(n)=n(n+1)2=n∑T=1S(⌊nT⌋)S(⌊mT⌋)T∑d|Tdμ(d) let T=dd′ ∗
再令 f(n)=n∑d|ndμ(d),由于化简不来,我们转而证明它积性可直接筛,具体可见下文「线性筛 trick」。
最终 O(n)−O(√n) 解决。
例三
51nod 1584.
令 σ(n) 为 n 的约数之和。给出 T 个 n,对于每个 n,求
n∑i=1n∑j=1max{i,j}σ(ij)mod(109+7)
T≤5×104,n≤106。
只要睡醒了应该是有把 max 拆开的意识的。原式化为
2n∑i=1ii∑j=1σ(ij)−n∑i=1iσ(i2)
σ(i2) 可证积性,直接筛出后一项。对于前一项,我们先来研究 σ(ij) 的性质:
引理:
σ(ij)=∑x|i∑y|jxy[x⊥jy]
证明:对于每个 d|ij,当且仅当 y=gcd(d,j), x=dy 时被统计一次。考虑一个 a|d∧a|i∧a|j,一定有 a/|x,不然就不可能有 x⊥jy,所以以上表述成立。
利用引理,记 f(n)=n∑ni=1σ(ni),推导:
f(n)=nn∑i=1∑x|n∑y|ixy[x⊥iy]=nn∑i=1∑x|n∑y|ixy∑d|x∧d|iyμ(d) ∗=nn∑i=1∑d|n∧d|iμ(d)∑x|n∧d|x∑y|i∧d|yixy=nn∑i=1∑d|n∧d|iμ(d)∑x|nd∑y|idixy, x,y 同时约掉 d=nn∑i=1∑d|n∧d|iμ(d)σ(nd)∑y|idiy=nn∑i=1∑d|n∧d|iμ(d)σ(nd)d∑y|idiyd=nn∑i=1∑d|n∧d|idμ(d)σ(nd)σ(id)=n∑d|ndμ(d)σ(nd)nd∑i=1σ(i)
筛出 μ,σ,枚举 d 和 nd,可以 O(nlnn) 算出所有 f,具体可见下文「O(nlnn) 刷表 trick」以及我的题解。
最终,O(nlnn)−O(1) 解决问题。
魔法中的 tricks
毕竟 Mobius 反演不能把所有式子化成一眼能求。当我们在推导过程中卡住的时候,可以尝试用一些 trick “暴力”计算得到的式子,说不定就是正解呢!
线性筛 trick
记住一句话:积性函数都能筛。
Euler 筛法的框架如下:
inline void sieve ( const int n ) {
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;
if ( i % pr[j] ) {
} else {
break;
}
}
}
}
难点只有两个:
- 如何判断某个函数是积性函数?
- 如何处理计算的 t 处点值?
对于前者,打表(迫真)和带入计算都是不错的选择。后者则需要根据函数表达式灵活处理,一般来说都是加减乘除能够解决的,某些情况(例如筛 σ1)需要额外记录信息。
筛 σ1
σ1 也简记作 σ,有定义
σ(n)=∑d|nd
则任意一对 x⊥y,带入
σ(x)σ(y)=∑dx|xdx∑dy|ydy=∑dx|x,dy|ydxdy=∑d|xyd=σ(xy)
第三步用了 x⊥y 的条件。可见 σ 积性,考虑如何筛。
小奥教会我们,对于 n=∏pαii(标准分解形式),有
σ(n)=∏αi∑j=0pji
证略。我们来处理筛法中的特殊情况,设 p=pk 为 x 的最小素因子,则应有 p2|x。观察:
σ(xp)=⎛⎝∏pi≠pαi∑j=0pji⎞⎠(αk∑j=0pj)σ(x)=⎛⎝∏pi≠pαi∑j=0pji⎞⎠(αk+1∑j=0pj)
乘积式很难直接修改某一项的值,所以我们需要对于每个 x,记录其最小素因子的贡献,记作 σp(x),有
σp(x)=αk∑j=0pj
σp 很显然可以在筛法中处理。此后,就能得到
σ(x)=σ(xp)σp(xp)σp(x)
问题解决。值得再次强调的是,Euler 筛法中的合数一定被其最小素因子筛掉。
筛 idkμ
即 洛谷 P4449 的阶段性问题。
做题的时候,经常遇见此类很多个基础的积性函数卷起来的函数,它们亦可被线性筛。
同样的姿势,设 p 为 x 的最小素因子,且有 p2|x,观察:
idkμ(xp)=∑d|xpdkμ(xdp)idkμ(x)=∑d|xdkμ(xd)
分类讨论第二个和式中的 d:
- 不含新加入的素因子 p,对应了第一个和式中的每个 dkμ(xdp),只不过 x 多了一个 p,所以应为 dkμ(xd)。由于 p2|x,且 d|xp⇒p|xd,故 μ(x)=μ(xd)=0,无贡献;
- 含有新加入的素因子 p,亦对应第一个和式中的每个 dkμ(xdp),只不过 d 多了一个 p,所以应为 dkpkμ(xdp)。
综上:
idkμ(x)=pk(idkμ)(xp)
筛 f(n)=n∑d|ndμ(d)
这是上文的问题,我们得证明它能筛(积性),在得出它如何筛。
还是惯用手法,带入任意 x⊥y:
f(x)f(y)=⎛⎝x∑dx|xdxμ(dx)⎞⎠⎛⎝y∑dy|ydyμ(dy)⎞⎠=xy∑dx|x,dy|ydxdyμ(dx)μ(dy)=xy∑d|xydμ(d)=f(xy)
果然积性。
当然,也可以用积性的延续性质。发现
f=((μ⋅id)⋆I)⋅id
亦能说明 f 积性。
接下来,我们从积性的角度着手,思考素数幂 pk 处的点值。边界有:
f(p)=p(1−p)
对于其他 k>1:
f(pk)=pkk∑i=0piμ(pi)=pk(1−p)=pf(pk−1)
所以在筛法中,有 p2|x,那么:
f(x)=pf(xp)
简洁地结束问题。
O(nlnn) 刷表 trick
基于 ∑ni=1ni=O(nlnn),很多时候可以把 Dirichlet 卷积形式的函数暴力打表出来。框架如下:
for ( int i = 1; i <= MAXN; ++i ) {
for ( int j = 1, t; ( t = i * j ) <= MAXN; ++j ) {
}
}
以前文求
f(n)=n∑d|ndμ(d)σ(nd)nd∑i=1σ(i)
为例,步骤如下:
-
常系数剔除:n 显然最后再乘上去。
-
形式变化:类似变化乘法卷积的操作,把式子变化成形如 ∑d|nA(d)B(nd) 的形式。此处有
f(n)n=∑d|n(dμ(d))⎛⎜⎝σ(nd)nd∑i=1σ(i)⎞⎟⎠
-
预处理上述 A(n),B(n) 的值。此处即筛出 μ 和 σ,预处理 σ 前缀和。
-
套用框架计算。
莫得什么难点。(
Conclusion
莫反题的难点一般不是莫反。(
Practice makes perfect. 式子多推一下自然能找到感觉。建议尝试自己推导文中的式子,再对照文中的推导看看是否可以优化。(当然我可能推得很细,也可能兔子就是要蠢一点 qwq。
更多莫反题可在 OI-Wiki 以及 我的博客 中挑选嗷~
终于写完了 qwq!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现