莫比乌斯反演学习笔记

本博客内容基本与https://www.cnblogs.com/chenyang920/p/4811995.html相同

文中的sigma表示累加。ps:中间遇到看不懂的请不要放弃,只把它当成已知结论即可,继续往后看可见证明。

一、什么是莫比乌斯反演

给出一个函数f(n),再由f(n)求得一个新函数g(n),g(n)=sigma(f(d))(d被包含于n)。可通过反演由g(n)求f(n)。

eg1:g(n)=sigma(f(i))(1<=i<=n),g(n)=n*(n-1)/2,求f(n)。

显然f(n)=n。

eg2:令s、x为集合,|s|、|x|表示s、x中的元素个数,f(s)、g(s)为定义在s集合上的函数。

g(s)=sigma(f(x))(x为s的子集),求f(s)。

根据现成的集合包含的莫比乌斯反演公式可得f(s)=sigma(((-1)^(|s|-|x|))*g(x)),可用程序进行验证,代码如下:

#include <iostream>
#include <math.h>
using namespace std;
#define base 10
#define REP(i,n) for(int i=0;i<(n);i++)
int F[1<<base],G[1<<base];
// 集合用二进制表示 base表示集合最多10个元素


int Cal(int x){ // 计算 |x|
    int sum=0;
    while(x) sum+=(x&1),x/=2;
    return sum;
}


int main(){
    REP(S,1<<base) F[S]=Cal(S); // 计算出最开始的F(S)
    REP(S,1<<base){   // 计算G(S)
        G[S]=0;
        for(int X=S;X;X=(X-1)&S) G[S]+=F[X]; //用X遍历S集合
    }
    REP(S,1<<base){     // 计算反演的 F(S)
        F[S]=0;
        for(int X=S;X;X=(X-1)&S)
            F[S]+=(int)pow(-1,Cal(S)-Cal(X))*G[X];
    }
    bool flag=1;    // 验证一下
    REP(S,1<<base)
        if(F[S]!=Cal(S)) flag=0;
    if(flag) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
}

二、一类反演

已知g(n)=sigma(f(d))(d|n,d是n的约数),求f(n)。

求得:f(n)=sigma(u(n/d)*g(d))。(不懂不要紧请继续往后看有证明!!!)

1.u(x)=-1(当且仅当x可分解为奇数个不同质数的乘积)

2.u(x)=1(当且仅当x可分解为偶数个不同质数的乘积)

3.u(x)=0(其他情况)

对于一个 x , 分解因式过后 有  x=(p1^e1)*(p2^e2)...*(pr^er)如果 ei中(1<=i<=r)有一个数ei大于1  那么  U[x] = 0;
不然的话   U[x] = (-1)^r

eg:u(6)=1(因为2*3=6,偶数个不同质数的乘积)

       u(2)=-1(因为2=2,奇数个不同质数的乘积)

       u(9)=0(因为9=3^2属于其他情况)

       u(12)=0(因为12=2^2*3属于其他情况)

证明:首先思考一下为什么f(n)会具有sigma(u(n/d)g(d))的形式呢?

我们通过一个例子来看一下,如何求解f(6)?

因为是已知g(n)求f(n),所以我们可求出g(6)、g(1)、g(2)、g(3)的值,根据定义得:

g(6)=f(1)+f(2)+f(3)+f(6)

g(2)=f(1)+f(2)

g(3)=f(1)+f(3)

g(1)=f(1)

显然可得f(6)=g(6)-g(2)-g(3)+g(1).

观察上面可得g(n)都是由f(n)累加得到的,需要求f(n)只需利用g(n)进行容斥可得。

现在我们知道了为什么反演公式会具有那样的形式,接下来思考怎样求解每个g的系数。

令h(d,n)表示求解f(n)时g(d)的系数(d|n,d整除n)

f(6)=h(6,6)*g(6)+h(2,6)*g(2)+h(3,6)*g(3)+h(1,6)*g(1)

那么f(6)=h(6,6)*(f(6)+f(3)+f(2)+f(1))+h(2,6)*(f(2)+f(1))+h(3,6)*(f(3)+f(1))+h(1,6)*f(1)

上述式子可变为f(6)*(h(6,6)-1)+f(3)*(h(6,6)+h(3,6))+f(2)*(h(6,6)+h(2,6))+f(1)*(h(6,6)+h(2,6)+h(3,6)+h(1,6))=0。

h(6,6)-1=0

h(6,6)+h(3,6)=0

h(6,6)+h(2,6)=0

h(6,6)+h(3,6)+h(2,6)+h(1,6)=0

四个方程四个未知数,所以可求得相应的解。对于每个f(n)设它有m个因子,总能列出m个方程,m个未知数,从而可得莫比乌斯反演方程是可解的。


接下来证明一件非常重要的事情h(a,b)=h(1,b/a)。

首先看一个非常简单的例子

f(8)=h(8,8)*g(8)+h(4,8)*g(4)+h(2,8)*g(2)+h(1,8)*g(1)

只有g(8)中含有f(8)所以h(8,8)=1=h(1,1)

h(4,8)=-h(8,8)=-h(2,2)=h(1,2)(因为f(2)=h(2,2)*g(2)+h(1,2)*g(1)所以-h(2,2)=h(1,2))

h(2,8)=-(h(8,8)+h(4,8))=-(h(4,4)+h(2,4))=h(1,4)

找到规律后,假设n有m个因子,d1,d2,d3......dm,h(di,n)受dj影响当且仅当dj>=di,di|dj,假设h(a,b)=h(1,)在求解dj及h(k,m)已经成立,那么h(dj,n)=h(1,n/dj)=h(dj/di,n/di)所以h(di,n)=h(1,n/di)。(因为h(di,n)=-sigma(h(dj,n))) 考虑f(n/di)那么h(1,n/di)=-sigma(h(di/di,n/di))。

此时考虑u(x)可知u(x)=h(1,x) u(x)表示在计算f(x)时g(1)的系数。下面分情况讨论u的值

一、g(x)一定包含f(1)

二、f(1)=g(1)  u(1)=1

a.如果x==1 f(1)=g(1) u[1]=1

b.如果x为质数 f(x)=u(x)*g(1)+u(1)*g(x) u(x)=-1

c.如果x=p*q(其中p,q不相等质数)

 f(x)=u(x)*g(1)+u(p)*g(q)+u(q)*g(p)+u(1)*g(x) u(p)、u(q)为b情况所以都等于-1,u(1)=1,所以u(x)=1

d.x=p*p1*p2(p,p1,p2为互不相同的质数)

f(x)=u(x)*g(1)+u(p1*p2)*g(p)+u(p*p2)*g(p1)+u(p*p2)*g(p1)+u(p2)*g(p*p1)+u(p1)*g(p*p2)+u(p)*g(p1*p2)+u(1)*g(x)

u(p1*p2)、u(p*p2)、u(p*p1)符合情况c等于1,

u(p)、u(p1)、u(p2)符合情况b等于-1,所以u(x)=-1.

所以u(x)=(-1)^r

e.x=p^2

f(x)=u(1)*g(x)+u(p)*g(p)+u(x)*g(1) u(p)=-1 所以u(x)=0 易证x=p^e*q  u(x)=0

五种情况都讨论完可得u(x)的取值规律。

1.u(x)=-1(当且仅当x可分解为奇数个不同质数的乘积)

2.u(x)=1(当且仅当x可分解为偶数个不同质数的乘积)

3.u(x)=0(其他情况)

三、应用

公式变式

原式 :  G(n)=sigma(F(d))  (其中n|d,d<=N)  
反演公式:   F(n)=sigma(U(d/n)*G(d))  (其中n|d,d<=N) 这里U[x]的计算方式和上面的相同!!


eg:给出a,b 其中 (1<=a,b<=10^6) 
求满足条件的 x,y 的对数,使得 1<=x<=a,1<=y<=b,且gcd(x,y) == 1。
其中 (2,3) (3,2) 算两对!

定义f(n)为gcd(x,y)=n的(x,y)对数

那么g(n)=sigma(f(d))(d|n) 即gcd(x,y)%n=0的(x,y)对数

那么g(i)=(a/i)*(b/i)

所以先用线筛求出各项系数即可得解!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值