本博客内容基本与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)
所以先用线筛求出各项系数即可得解!!