zoukankan      html  css  js  c++  java
  • Note -「Mobius 反演」光速入门

      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(k)=sum_{ioplus j=k}f(i)cdot g(j) ]

      则 (h)(f)(g)(oplus) 卷积。例如 (oplus) 为加号,则 (h)(f)(g) 的普通卷积;若 (oplus) 为异或,则 (h)(f)(g) 的异或卷积。

      而当 (oplus) 为乘号,(f,g,h) 为数论函数,有

    [h(k)=sum_{ij=k}f(i)cdot g(j) ]

      此时 (h) 即为 (f)(g) Dirichlet 卷积的结果。记为

    [h=fstar g ]

      当然,另一种表达方式为

    [h(k)=sum_{i|n}f(i)cdot g(frac{k}i) ]

      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)

    [egin{aligned} h(x)h(y)&=left(sum_{d_x|x}f(d_x)g(frac{x}{d_x}) ight)left(sum_{d_y|y}f(d_y)g(frac{y}{d_y}) ight)\ &=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) 是一个积性函数,定义式为:

    [mu(n)=egin{cases} 1&n=1\ (-1)^k&n=p_1p_2cdots p_k,~~~~p ext{ 为两两不同的素数}\ 0& ext{otherwise} end{cases} ]

      这样看着很臃肿。注意 (mu) 是一个积性函数,我们只需要描述起在 (p^c~(cinmathbb N_+)) 处的点值。可以看出:

    [mu(p^c)=[c=1](-1) ]

      (mu) 函数是为了满足下式:

    [Istarmu=epsilon ]

      即:

    [sum_{d|n}mu(d)=[n=1] ]

      证明(n=1) 时显然成立,仅需证明 (n>1) 时左式恒为 (0)。设 (n=prod p_i^{alpha_i}),显然仅需考虑左式中 (d=prod p_i) 时的和。不妨设 (n) 含有素因子的集合为 (P),则左式有:

    [egin{aligned} sum_{d|n}mu(d)&=sum_{Ssubseteq P}mu(prod_{pin S}p)\ &=sum_{Ssubseteq P}(-1)^{|S|}\ &=sum_{|S|in[0,|P|]}inom{|P|}{|S|}(-1)^{|S|}\ &=(1-1)^{|P|}\ &=0^{|P|}~~~~(|P|>0)\ &=0 end{aligned} ]

      在此后的推导中,我们通常仅把 (mu) 看做“(I) 的逆元”而不考虑其内部表达式,故多数情况不需要如此考虑其展开后的运算。

    Mobius 反演

      充分认识 (mu) 之后,反演公式其实非常浅显。对于两个数论函数 (f,g),满足:

    [f=gstar ILongleftrightarrow g=fstarmu ]

      证明:左式左右同时卷 (mu) 即证 (Rightarrow);右式左右同时卷 (I) 即证 (Leftarrow)

      还有两种和式形式:

    [f(n)=sum_{d|n}g(d)Longleftrightarrow g(n)=sum_{d|n}f(d)mu(frac{n}d) ag1 ]

    [f(n)=sum_{n|d}g(d)Longleftrightarrow g(n)=sum_{n|d}f(d)mu(frac{d}n) ag2 ]

      ((1)) 即为卷积形式,已证,下证 ((2))

      证明,仅证 (Rightarrow),倒推结论:

    [egin{aligned} 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)

    [egin{aligned} sigma_0(n)&=sum_{d|n}1\ &=sum_{d|n}I(d)I(frac{n}d)\ &=I^2(n) end{aligned} ]

      结论:

    [sigma_0=I^2 ]

    欧拉函数 (varphi)

      定义式:(varphi(n)=sum_{i=1}^n[iperp n])

    [egin{aligned} varphi(n)&=sum_{i=1}^n[iperp n]\ &=sum_{i=1}^nsum_{d|iland d|n}mu(d)~~~~*\ &=sum_{d|n}mu(d)frac{n}d\ &=sum_{d|n}mu(d)operatorname{id}(frac{n}d)\ &=(mustaroperatorname{id})(n) end{aligned} ]

      标注 (*) 的步骤运用了 Mobius 反演,下文亦如此。结论:

    [varphi=mustaroperatorname{id} ]

    反演魔法

    例一

      类似题目 Link.

      给定 (n,m,k),求

    [sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=k] ]

      传说中的七倍经验题。直接来叭:

    [egin{aligned} sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=k]&=sum_{i=1}^{lfloorfrac{n}k floor}sum_{j=1}^{lfloorfrac{m}k floor}[iperp j]\ &=sum_{i=1}^{lfloorfrac{n}k floor}sum_{j=1}^{lfloorfrac{m}k floor}sum_{d|iland d|j}mu(d)~~~~*\ &=sum_{d=1}^{min{lfloorfrac{n}k floor,lfloorfrac{m}k floor}}mu(d)lfloorfrac{n}{kd} floorlfloorfrac{m}{kd} floor end{aligned} ]

      (mathcal O(n)) 预处理后整除分块即可 (mathcal O(sqrt n)) 求解。整除分块是莫反题中高频出现的 trick,一定要用熟。

    例二

      BZOJ 2693.

      给定 (T)(n,m),对于每组,求

    [sum_{i=1}^nsum_{j=1}^moperatorname{lcm}(i,j)mod(10^8+9) ]

      (Tle10^4)(n,mle10^7)

      式子很简单,主要运用换元法

    [egin{aligned} sum_{i=1}^nsum_{j=1}^moperatorname{lcm}(i,j)&=sum_{d=1}^ndsum_{i=1}^{lfloorfrac{n}d floor}sum_{i=1}^{lfloorfrac{m}d floor}ij[iperp j]\ &=sum_{d=1}^ndsum_{d'=1}^{lfloorfrac{n}{d} floor}S(lfloorfrac{n}{dd'} floor)S(lfloorfrac{m}{dd'} floor)d'^2~~~~ ext{let }S(n)=frac{n(n+1)}2\ &=sum_{T=1}^nS(lfloorfrac{n}T floor)S(lfloorfrac{m}T floor)Tsum_{d|T}dmu(d)~~~~ ext{let } T=dd'~~~~* end{aligned} ]

      再令 (f(n)=nsum_{d|n}dmu(d)),由于化简不来,我们转而证明它积性可直接筛,具体可见下文「线性筛 trick」。

      最终 (mathcal O(n)-mathcal O(sqrt n)) 解决。

    例三

      51nod 1584.

      令 (sigma(n))(n) 的约数之和。给出 (T)(n),对于每个 (n),求

    [sum_{i=1}^nsum_{j=1}^nmax{i,j}sigma(ij)mod(10^9+7) ]

      (Tle5 imes10^4)(nle10^6)

      只要睡醒了应该是有把 (max) 拆开的意识的。原式化为

    [2sum_{i=1}^nisum_{j=1}^isigma(ij)-sum_{i=1}^nisigma(i^2) ]

      (sigma(i^2)) 可证积性,直接筛出后一项。对于前一项,我们先来研究 (sigma(ij)) 的性质:

      引理

    [sigma(ij)=sum_{x|i}sum_{y|j}xy[xperp frac{j}y] ]

      证明:对于每个 (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)),推导:

    [egin{aligned} f(n)&=nsum_{i=1}^nsum_{x|n}sum_{y|i}xy[xperpfrac{i}y]\ &=nsum_{i=1}^nsum_{x|n}sum_{y|i}xysum_{d|xland d|frac{i}y}mu(d)~~~~*\ &=nsum_{i=1}^nsum_{d|nland d|i}mu(d)sum_{x|nland d|x}sum_{y|iland d|y}frac{ix}y\ &=nsum_{i=1}^nsum_{d|nland d|i}mu(d)sum_{x|frac{n}d}sum_{y|frac{i}d}frac{ix}y,~~~~x,ymbox{ 同时约掉 } d\ &=nsum_{i=1}^nsum_{d|nland d|i}mu(d)sigma(frac{n}d)sum_{y|frac{i}d}frac{i}y\ &=nsum_{i=1}^nsum_{d|nland d|i}mu(d)sigma(frac{n}d)dsum_{y|frac{i}d}frac{frac{i}y}d\ &=nsum_{i=1}^nsum_{d|nland d|i}dmu(d)sigma(frac{n}d)sigma(frac{i}d)\ &=nsum_{d|n}dmu(d)sigma(frac{n}d)sum_{i=1}^frac{n}{d}sigma(i) end{aligned} ]

      筛出 (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),有定义

    [sigma(n)=sum_{d|n}d ]

      则任意一对 (xperp y),带入

    [egin{aligned} sigma(x)sigma(y)&=sum_{d_x|x}d_xsum_{d_y|y}d_y\ &=sum_{d_x|x,d_y|y}d_xd_y\ &=sum_{d|xy}d\ &=sigma(xy) end{aligned} ]

      第三步用了 (xperp y) 的条件。可见 (sigma) 积性,考虑如何筛。

      小奥教会我们,对于 (n=prod p_i^{alpha_i})(标准分解形式),有

    [sigma(n)=prod sum_{j=0}^{alpha_i}p_i^j ]

      证略。我们来处理筛法中的特殊情况,设 (p=p_k)(x) 的最小素因子,则应有 (p^2|x)。观察:

    [sigma(frac{x}p)=left(prod_{p_i ot=p}sum_{j=0}^{alpha_i}p_i^j ight)left(sum_{j=0}^{alpha_k}p^j ight)\ sigma(x)=left(prod_{p_i ot=p}sum_{j=0}^{alpha_i}p_i^j ight)left(sum_{j=0}^{alpha_k+1}p^j ight) ]

      乘积式很难直接修改某一项的值,所以我们需要对于每个 (x),记录其最小素因子的贡献,记作 (sigma_p(x)),有

    [sigma_p(x)=sum_{j=0}^{alpha_k}p^j ]

      (sigma_p) 很显然可以在筛法中处理。此后,就能得到

    [sigma(x)=frac{sigma(frac{x}p)}{sigma_p(frac{x}p)}sigma_p(x) ]

      问题解决。值得再次强调的是,Euler 筛法中的合数一定被其最小素因子筛掉

    (operatorname{id}^kmu)

      即 洛谷 P4449 的阶段性问题。

      做题的时候,经常遇见此类很多个基础的积性函数卷起来的函数,它们亦可被线性筛。

      同样的姿势,设 (p)(x) 的最小素因子,且有 (p^2|x),观察:

    [operatorname{id}^kmu(frac{x}p)=sum_{d|frac{x}p}d^kmu(frac{x}{dp})\ operatorname{id}^kmu(x)=sum_{d|x}d^kmu(frac{x}d) ]

      分类讨论第二个和式中的 (d)

    1. 不含新加入的素因子 (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),无贡献;
    2. 含有新加入的素因子 (p),亦对应第一个和式中的每个 (d^kmu(frac{x}{dp})),只不过 (d) 多了一个 (p),所以应为 (d^kp^kmu(frac{x}{dp}))

      综上:

    [operatorname{id}^kmu(x)=p^k(operatorname{id}^kmu)(frac{x}p) ]

    (f(n)=nsum_{d|n}dmu(d))

      这是上文的问题,我们得证明它能筛(积性),在得出它如何筛。

      还是惯用手法,带入任意 (xperp y)

    [egin{aligned} f(x)f(y)&=left( xsum_{d_x|x}d_xmu(d_x) ight)left( ysum_{d_y|y}d_ymu(d_y) ight)\ &=xysum_{d_x|x,d_y|y}d_xd_ymu(d_x)mu(d_y)\ &=xysum_{d|xy}dmu(d)\ &=f(xy) end{aligned} ]

      果然积性。

      当然,也可以用积性的延续性质。发现

    [f=((mucdotoperatorname{id})star I)cdotoperatorname{id} ]

      亦能说明 (f) 积性。

      接下来,我们从积性的角度着手,思考素数幂 (p^k) 处的点值。边界有:

    [f(p)=p(1-p) ]

      对于其他 (k>1)

    [egin{aligned} f(p^k)&=p^ksum_{i=0}^kp^imu(p^i)\ &=p^k(1-p)\ &=pf(p^{k-1}) end{aligned} ]

      所以在筛法中,有 (p^2|x),那么:

    [f(x)=pf(frac{x}p) ]

      简洁地结束问题。

    (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 贡献 */
        }
    }
    

      以前文求

    [f(n)=nsum_{d|n}dmu(d)sigma(frac{n}d)sum_{i=1}^frac{n}{d}sigma(i) ]

      为例,步骤如下:

    1. 常系数剔除:(n) 显然最后再乘上去。

    2. 形式变化:类似变化乘法卷积的操作,把式子变化成形如 (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) ]

    3. 预处理上述 (A(n))(B(n)) 的值。此处即筛出 (mu)(sigma),预处理 (sigma) 前缀和。

    4. 套用框架计算。

      莫得什么难点。(

    Conclusion

      莫反题的难点一般不是莫反。(

      Practice makes perfect. 式子多推一下自然能找到感觉。建议尝试自己推导文中的式子,再对照文中的推导看看是否可以优化。(当然我可能推得很细,也可能兔子就是要蠢一点 qwq。

      更多莫反题可在 OI-Wiki 以及 我的博客 中挑选嗷~

      终于写完了 qwq!

  • 相关阅读:
    做才是得到
    常用工具汇总
    迎接2017
    新年礼物
    2017
    asp.net core 日志
    板子|无向图的割点
    11/06信竞快乐模拟赛
    动态规划复习
    894D
  • 原文地址:https://www.cnblogs.com/rainybunny/p/14359098.html
Copyright © 2011-2022 走看看