zoukankan      html  css  js  c++  java
  • 莫比乌斯反演

    目录

    目录地址

    上一篇

    下一篇


    莫比乌斯反演的原理

    由定义,对于两个积性函数 (oldsymbol f,oldsymbol g) 若满足 (displaystyle oldsymbol g(n)=sum_{dmid n}oldsymbol f(d))

    则根据 (oldsymbol g=oldsymbol f*oldsymbol I) 反推出 (oldsymbol f=oldsymbol g*oldsymbol mu)

    从而有 (displaystyle oldsymbol f(n)=sum_{dmid n}oldsymbol g(d)cdot oldsymbol mu({nover d}))

    当然,本人更爱使用元函数的反演法,即将式子中化简出 ([n=1]) 项,再通过 (displaystyle [n=1]=oldsymbol varepsilon(n)=(oldsymbol mu*oldsymbol I)(n)=sum_{dmid n}oldsymbol mu(n)) 反演出结果


    另一方向的莫比乌斯反演

    当然,铃悬 dalao 还给出了另一个方向的莫比乌斯反演:

    (displaystyle oldsymbol g(n)=sum_{nmid m}oldsymbol f(m)) 反演为 (displaystyle oldsymbol f(n)=sum_{nmid m}oldsymbol mu({mover n})oldsymbol g(m))

    证明方法来源于 铃悬的数学小讲堂——狄利克雷卷积与莫比乌斯反演

    我们定义一个运算 (displaystyle (oldsymbol foplusoldsymbol g)(n)=sum_{nmid m}oldsymbol f({mover n})cdot oldsymbol g(m))

    很显然,根据定义 (displaystyle (oldsymbol varepsilonoplus oldsymbol f)(n)=sum_{nmid m}oldsymbol varepsilon({mover n})cdot oldsymbol f(m)=sum_{nmid m,m eq n}oldsymbol varepsilon({mover n})cdot oldsymbol f(m)+oldsymbol varepsilon({nover n})cdot oldsymbol f(n)=0+1cdot oldsymbol f(n)=oldsymbol f(n))

    所以我们可以知道,原式为 (oldsymbol g=oldsymbol Ioplus oldsymbol f) ,反演式为 (oldsymbol f=oldsymbol muoplus oldsymbol g)

    考虑到 (displaystyle ( (oldsymbol f*oldsymbol g)oplus oldsymbol h)(n)=sum_{nmid m}(oldsymbol f*oldsymbol g)({mover n})cdot oldsymbol h(m)=sum_{nmid m}(sum_{dmid {mover n}}oldsymbol f(d)oldsymbol g({mover nd}) )cdot oldsymbol h(m)=sum_{nmid m}(sum_{ndmid m}oldsymbol f(d)oldsymbol g({mover nd}) )cdot oldsymbol h(m))

    由于对于所有满足加和条件的 (d)(oldsymbol h(m)) 都是固定的,所以可以将括号展开,原式 (displaystyle =sum_{nmid m}sum_{ndmid m}oldsymbol f(d)oldsymbol g({mover nd})cdot oldsymbol h(m))

    我们令 (T=nd) 所以 (Tmid m) 则可以肯定 (nmid m)

    但是我们还需要额外加上条件 (nmid T) 即可保证符合原式的性质

    因此,原式 (displaystyle =sum_{nmid T}sum_{Tmid m}oldsymbol f({Tover n})cdot oldsymbol g({mover T})cdot oldsymbol h(m)=sum_{nmid T}oldsymbol f({Tover n})cdot ( sum_{Tmid m}oldsymbol g({mover T})cdot oldsymbol h(m) )=sum_{nmid T}oldsymbol f({Tover n})cdot (oldsymbol goplusoldsymbol h)(T)=(oldsymbol foplus(oldsymbol goplus oldsymbol h) )(n))

    故我们得到 ((oldsymbol f*oldsymbol g)oplus oldsymbol h=oldsymbol foplus (oldsymbol goplus oldsymbol h))

    现在,我们可以很简单地证明上述式子的正确性了:

    (oldsymbol f=oldsymbol varepsilonoplus oldsymbol f=(oldsymbol mu*oldsymbol I)oplus oldsymbol f=oldsymbol muoplus(oldsymbol Ioplus oldsymbol f)=oldsymbol muoplus oldsymbol g)

    所以上述式子成立


    莫比乌斯反演例题

    洛谷P4450 双亲数

    给定 (A,B,d)(displaystyle ans=sum_{a=1}^Asum_{b=1}^B[gcd(a,b)=d])

    第一题,咱们讲细一点......

    我们不妨设 (Aleq B) ,否则我们交换这两个

    考虑到 (a) 只有 (d,2d,3dcdots (A/d)cdot d) 时对答案有贡献, (b) 也是 (d,2d,3dcdots (B/d)cdot d) 时对答案有贡献

    故我们直接改为枚举前面的系数,它们乘上 (d) 就是 (a,b)

    (displaystyle ans=sum_{a'=1}^{(A/d)}sum_{b'=1}^{(B/d)}[gcd(a'd,b'd)=d]=sum_{a'=1}^{(A/d)}sum_{b'=1}^{(B/d)}[dcdot gcd(a',b')=d]=sum_{a'=1}^{(A/d)}sum_{b'=1}^{(B/d)}[gcd(a',b')=1])

    这里可以用上元函数反演 (displaystyle [n=1]=oldsymbol varepsilon(n)=(oldsymbol mu*oldsymbol I)(n)=sum_{dmid n}oldsymbol mu(d))

    因此直接代入上式得到 (displaystyle ans=sum_{a=1}^{A/d}sum_{B=1}^{B/d}sum_{kmid gcd(a,b)}oldsymbol mu(k))

    要满足 (kmid gcd(a,b)) ,即 (k)(a,b) 最大公因数的因数,因此一定为其公因数,可写为 (kmid awedge kmid b)

    (displaystyle ans=sum_{a=1}^{A/d}sum_{b=1}^{B/d}sum_{kmid awedge kmid b}oldsymbol mu(k)=sum_{a=1}^{A/d}sum_{b=1}^{B/d}sum_{k=1}^{A/d}oldsymbol mu(k)[kmid awedge kmid b])

    我们调换枚举顺序,先枚举 (k)

    (displaystyle ans=sum_{k=1}^{A/d}oldsymbol mu(k)sum_{a=1}^{A/d}sum_{b=1}^{B/d}[kmid awedge kmid b])

    由于 ([kmid awedge kmid b]) 可以理解为一个 bool ,所以它与 ([kmid a]cdot [kmid b]) 等价

    再次代入得 (displaystyle ans=sum_{k=1}^{A/d}oldsymbol mu(k)sum_{a=1}^{A/d}sum_{b=1}^{B/d}[kmid a][kmid b]=sum_{k=1}^{A/d}oldsymbol mu(k)sum_{a=1}^{A/d}[kmid a]sum_{b=1}^{B/d}[kmid b])

    我们单独考虑 (displaystyle sum_{a=1}^{A/d}[kmid a]) 有贡献的肯定是 (k,2k,3kcdots ( (A/d)/k)cdot k) 因此我们枚举有贡献的

    (displaystyle sum_{a=1}^{A/d}[kmid a]=sum_{a'=1}^{(A/d)/k}[akmid a]=sum_{a'=1}^{A/(dk)}1=A/(dk))

    同理处理 (B) 的式子后,我们得到 (displaystyle ans=sum_{k=1}^{A/d}oldsymbol mu(k)cdot (A/(dk) )cdot (B/(dk) ))

    由于 (A,B,d) 是开头给定的,因此我们不妨直接令 (A'=A/d,B'=B/d) 即可得到 (displaystyle ans=sum_{k=1}^{A'}oldsymbol mu(k)cdot (A'/k)cdot (B'/k))

    我们先预处理莫比乌斯函数前缀和,再用二维整出分块搞一搞后面就可以 (O(n+sqrt n)) 的时间搞出来了, (n)(A,B) 同阶

    简单补充一下二维整除分块:考虑对 (forall iin [l,r]) 使得 (egin{cases} n/(l-1) eq n/l=n/i=n/r eq n/(r+1) \ \ m/(l-1) eq m/l=m/i=m/r eq m/(r+1) end{cases})

    我们以已知左端点的为例,若对于 (n) ,可以求出一个 (r_n) ;对于 (m) ,可以求出一个 (r_m) ;则 (min(r_n,r_m)) 就是上述满足上述条件的 (r)

    if(a>b) swap(a,b);
    int ans=0;
    for(int l=1,r;l<=a;l=r+1){
        r=min(a/(a/l),b/(b/l));
        ans+=(smu[r]-smu[l-1])*(a/l)*(b/l);
    }
    

    洛谷P3455 [POI2007]ZAP-Queries

    与上一题大同小异,只不过改成了 (n) 次的查询,复杂度改为预处理 (O(a)) 加上算后面那一项的 (n)(O(nsqrt a))

    由于 (n,a) 同阶,复杂度为 (O(nsqrt n))

    由于式子都是一样的,这题就不推了,答案最后是 (displaystyle ans=sum_{x=1}^{a/d}oldsymbolmu(d)cdot( (a/d)/x )cdot( (b/d)/x ))

    洛谷P2257 YY的GCD

    推的过程类似,下面就没很多说明了

    我们要求 (displaystyle ans=sum_{i=1}^nsum_{j=1}^m[gcd(i,j)in Prime])

    我们改为枚举质数:(同样默认 $nleq m $ )

    (displaystyle ans=sum_{pin Prime}sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=p]=sum_{pin Prime}sum_{i=1}^{n/p}sum_{j=1}^{m/p}sum_{dmid iwedge dmid j}oldsymbolmu(d))

    ( herefore displaystyle ans=sum_{pin Prime}sum_{d=1}^{n/p}oldsymbolmu(d)sum_{i=1}^{n/p}[dmid i]sum_{j=1}^{m/p}[dmid j]=sum_{pin Prime}sum_{d=1}^{n/p}oldsymbolmu(d)cdot ( (n/p)/d )cdot ( (m/p)/d ))

    由于这样枚举 (d) 太不优雅了,因此我们不妨令 (T=pd) ,由于 (dleq n/p) 因此 (Tleq n)

    ( herefore displaystyle ans=sum_{pin Prime}sum_{T=1}^n oldsymbolmu({Tover p})cdot [pmid T] (n/T)cdot (m/T)=sum_{T=1}^n(n/T)cdot (m/T)cdot sum_{pin Prime}oldsymbol mu({Tover p})[pmid T]=sum_{T=1}^n(n/T)cdot (m/T)cdot sum_{pin Prime,pmid T}oldsymbol mu({Tover p}))

    为了表述方便,我们记录 (displaystyle f(T)=sum_{pin Prime,pmid T}oldsymbol mu({Tover p}))

    于是可以 (displaystyle ans=sum_{T=1}^n(n/T)cdot (m/T)cdot f(T))

    预处理好 (f(n)) ,剩下的就整出分块来搞一搞了

    给出预处理的代码:

    inline void sieve(){...}
    inline void pre(){
        for(int i=1;i<=cntprime;i++){
            int p=prime[i];
            for(int j=1;j*p<=lim;j++){
                sumf[j*p]+=mu[j];
            }
        }
    
        for(int i=1;i<=n;i++){
            sumf[i]+=sumf[i-1];
        }
    }
    

    洛谷P2522 [HAOI2011]Problem b

    (displaystyle ans=sum_{i=a}^bsum_{j=c}^d[gcd(i,j)=k])

    考虑 (displaystyle S(m,n)=sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=k]=sum_{d=1}^{n/k}oldsymbol mu(d)cdot ( (n/k)/d )cdot ( (m/k)/d ))

    求解 (S(n,m)) 方法见上文

    另外,由二维差分可以得到 (ans=S(b,d)-S(a-1,d)-S(b,c-1)+S(a-1,c-1))

  • 相关阅读:
    eclipse 提交代码至自己的github上
    今天是国庆
    我要完蛋了!!!
    C/C++知识点
    [c++]const增强
    [c++]指针作为函数参数传递的问题
    day3_JavaScript
    day2_HTML&CSS
    2017年度总结
    小游戏
  • 原文地址:https://www.cnblogs.com/JustinRochester/p/12491411.html
Copyright © 2011-2022 走看看