UPD:修改了 Euler 筛法代码框架。
若无特别说明,(x,y) 等形式变量均 (inmathbb N_+);(p) 为素数。
Preface
数论函数
我们称任意 (f:mathbb N_+ ightarrowmathbb C) 为一个数论函数。
积性函数
对于两个数论函数 (f),若对于任意 (xperp y)(即 (x,y) 互素,或说 (gcd(x,y)=1)),都有 (f(x)cdot f(y)=f(xy)),那么称此数论函数是积性函数,且显然有 (f(1)=1)。
可以发现,在此定义下,我们只需要知道该函数在素数幂((p^c~(cinmathbb N_+)))处的点值,就能还原整个函数。
特别地,若任意 (x,y) 都有 (f(x)cdot f(y)=f(xy)),那么称此数论函数是完全积性函数。例如,(I(n)=1) 是一个常函数,自然可以得到它是一个完全积性函数。
重要的一点是,绝大部分积性函数可以在 Euler 筛法的框架下快速求出所有点值。
积性在一些函数运算中得以延续。设 (f,g) 为积性函数,(kinmathbb N_+),则:
- (h(n)=(f(n))^k) 积性(不写作 (f^k(n)) 是为区别 Dirichlet 卷积);
- (h(n)=f(n^k)) 积性;
- (h(n)=f(n)cdot g(n)) 积性;
- (h(n)=(fstar 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 卷积有以下性质:
- 交换律:(fstar g=gstar f);
- 结合律:((fstar g)star h=fstar(gstar h));
- 分配律:(fstar(g+h)=fstar g+fstar h)。
带入可证,此处略过。
Dirichlet 卷积还有一个重要性质:若 (f,g) 积性,则 (h=fstar g) 积性。
证明:对于任意 (xperp y):
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) 是一个积性函数,定义式为:
这样看着很臃肿。注意 (mu) 是一个积性函数,我们只需要描述起在 (p^c~(cinmathbb N_+)) 处的点值。可以看出:
(mu) 函数是为了满足下式:
即:
证明:(n=1) 时显然成立,仅需证明 (n>1) 时左式恒为 (0)。设 (n=prod p_i^{alpha_i}),显然仅需考虑左式中 (d=prod p_i) 时的和。不妨设 (n) 含有素因子的集合为 (P),则左式有:
在此后的推导中,我们通常仅把 (mu) 看做“(I) 的逆元”而不考虑其内部表达式,故多数情况不需要如此考虑其展开后的运算。
Mobius 反演
充分认识 (mu) 之后,反演公式其实非常浅显。对于两个数论函数 (f,g),满足:
证明:左式左右同时卷 (mu) 即证 (Rightarrow);右式左右同时卷 (I) 即证 (Leftarrow)。
还有两种和式形式:
((1)) 即为卷积形式,已证,下证 ((2))。
证明,仅证 (Rightarrow),倒推结论:
基础应用
我们来推导几个常见的函数或式子。
约数个数 (sigma_0)
定义式:(sigma_0(n)=sum_{d|n}1)。
结论:
欧拉函数 (varphi)
定义式:(varphi(n)=sum_{i=1}^n[iperp n])。
标注 (*) 的步骤运用了 Mobius 反演,下文亦如此。结论:
反演魔法
例一
类似题目 Link.
给定 (n,m,k),求
传说中的七倍经验题。直接来叭:
(mathcal O(n)) 预处理后整除分块即可 (mathcal O(sqrt n)) 求解。整除分块是莫反题中高频出现的 trick,一定要用熟。
例二
给定 (T) 组 (n,m),对于每组,求
(Tle10^4),(n,mle10^7)。
式子很简单,主要运用换元法
再令 (f(n)=nsum_{d|n}dmu(d)),由于化简不来,我们转而证明它积性可直接筛,具体可见下文「线性筛 trick」。
最终 (mathcal O(n)-mathcal O(sqrt n)) 解决。
例三
令 (sigma(n)) 为 (n) 的约数之和。给出 (T) 个 (n),对于每个 (n),求
(Tle5 imes10^4),(nle10^6)。
只要睡醒了应该是有把 (max) 拆开的意识的。原式化为
(sigma(i^2)) 可证积性,直接筛出后一项。对于前一项,我们先来研究 (sigma(ij)) 的性质:
引理:
证明:对于每个 (d|ij),当且仅当 (y=gcd(d,j),~x=frac{d}y) 时被统计一次。考虑一个 (a|dland a|iland a|j),一定有 (a ot|x),不然就不可能有 (xperp frac{j}y),所以以上表述成立。
利用引理,记 (f(n)=nsum_{i=1}^nsigma(ni)),推导:
筛出 (mu,sigma),枚举 (d) 和 (frac{n}d),可以 (mathcal O(nln n)) 算出所有 (f),具体可见下文「(mathcal O(nln n)) 刷表 trick」以及我的题解。
最终,(mathcal O(nln 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]
ot| i,利用积性处理 t 处点值 */
} else {
/* pr[j] | i,特殊处理 t 处点值 */
break;
}
}
}
}
难点只有两个:
- 如何判断某个函数是积性函数?
- 如何处理计算的 (t) 处点值?
对于前者,打表(迫真)和带入计算都是不错的选择。后者则需要根据函数表达式灵活处理,一般来说都是加减乘除能够解决的,某些情况(例如筛 (sigma_1))需要额外记录信息。
筛 (sigma_1)
(sigma_1) 也简记作 (sigma),有定义
则任意一对 (xperp y),带入
第三步用了 (xperp y) 的条件。可见 (sigma) 积性,考虑如何筛。
小奥教会我们,对于 (n=prod p_i^{alpha_i})(标准分解形式),有
证略。我们来处理筛法中的特殊情况,设 (p=p_k) 为 (x) 的最小素因子,则应有 (p^2|x)。观察:
乘积式很难直接修改某一项的值,所以我们需要对于每个 (x),记录其最小素因子的贡献,记作 (sigma_p(x)),有
(sigma_p) 很显然可以在筛法中处理。此后,就能得到
问题解决。值得再次强调的是,Euler 筛法中的合数一定被其最小素因子筛掉。
筛 (operatorname{id}^kmu)
即 洛谷 P4449 的阶段性问题。
做题的时候,经常遇见此类很多个基础的积性函数卷起来的函数,它们亦可被线性筛。
同样的姿势,设 (p) 为 (x) 的最小素因子,且有 (p^2|x),观察:
分类讨论第二个和式中的 (d):
- 不含新加入的素因子 (p),对应了第一个和式中的每个 (d^kmu(frac{x}{dp})),只不过 (x) 多了一个 (p),所以应为 (d^kmu(frac{x}d))。由于 (p^2|x),且 (d|frac{x}pRightarrow p|frac{x}d),故 (mu(x)=mu(frac{x}d)=0),无贡献;
- 含有新加入的素因子 (p),亦对应第一个和式中的每个 (d^kmu(frac{x}{dp})),只不过 (d) 多了一个 (p),所以应为 (d^kp^kmu(frac{x}{dp}))。
综上:
筛 (f(n)=nsum_{d|n}dmu(d))
这是上文的问题,我们得证明它能筛(积性),在得出它如何筛。
还是惯用手法,带入任意 (xperp y):
果然积性。
当然,也可以用积性的延续性质。发现
亦能说明 (f) 积性。
接下来,我们从积性的角度着手,思考素数幂 (p^k) 处的点值。边界有:
对于其他 (k>1):
所以在筛法中,有 (p^2|x),那么:
简洁地结束问题。
(mathcal O(nln n)) 刷表 trick
基于 (sum_{i=1}^nfrac{n}i=mathcal O(nln 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(dmu(d) ight)left(sigma(frac{n}d)sum_{i=1}^{frac{n}d}sigma(i) ight) ] -
预处理上述 (A(n)),(B(n)) 的值。此处即筛出 (mu) 和 (sigma),预处理 (sigma) 前缀和。
-
套用框架计算。
莫得什么难点。(
Conclusion
莫反题的难点一般不是莫反。(
Practice makes perfect. 式子多推一下自然能找到感觉。建议尝试自己推导文中的式子,再对照文中的推导看看是否可以优化。(当然我可能推得很细,也可能兔子就是要蠢一点 qwq。
终于写完了 qwq!