莫比乌斯反演

莫比乌斯函数

莫比乌斯函数,定义如下:

  • d = 1 d=1 d=1 μ ( d ) = 1 μ(d)=1 μ(d)=1

  • d = p 1 p 2 … p k d=p_1p_2\dots p_k d=p1p2pk为互异素数,那么 μ ( d ) = ( − 1 ) k μ(d)=(-1)^k μ(d)=(1)k

  • 其它情况下 μ ( d ) = 0 μ(d)=0 μ(d)=0

莫比乌斯函数的性质

对于任意正整数 n n n有:

​ 若 n = 1 , ∑ d ∣ n μ ( d ) = 1 n=1,\sum\limits_{d|n}μ(d)=1 n=1,dnμ(d)=1

​ 若 n > 1 , ∑ d ∣ n μ ( d ) = 0 n>1,\sum\limits_{d|n}μ(d)=0 n>1,dnμ(d)=0

证明:

  • n = 1 n=1 n=1时显然

  • n > 1 n>1 n>1时,将分解可以得到 n = p 1 a 1 p 2 a 2 … p k a k n=p^{a_{1}}_{1}p^{a_{2}}_{2}\dots p^{a_{k}}_{k} n=p1a1p2a2pkak

​ 在 n n n的所有因子中, μ μ μ值不为零的只有所有质因子次数都为1的因子,其中质因数个数为 r r r个的因子有 C k r C^r_{k} Ckr个。

那么显然有:

∑ d ∣ n μ ( d ) = C k 0 − C k 1 + C k 2 − ⋯ + ( − 1 ) k C k k = ∑ i = 0 k ( − 1 ) i C k i \sum\limits_{d|n}μ(d)=C^0_{k}-C^1_{k}+C^2_{k}-\dots+(-1)^k C^k_{k}=\sum\limits^k_{i=0}(-1)^i C^i_{k} dnμ(d)=Ck0Ck1+Ck2+(1)kCkk=i=0k(1)iCki

只需证明 ∑ i = 0 n ( − 1 ) i C n i = 0 ( n ∈ N + ) \sum\limits^n_{i=0}(-1)^i C^i_{n}=0(n\in N_{+}) i=0n(1)iCni=0(nN+)即可。

二项式定理: ( x + y ) n = ∑ i = 0 n C n i x i y ( n − i ) (x+y)^n=\sum\limits^n_{i=0}C^i_{n}x^iy^{(n-i)} (x+y)n=i=0nCnixiy(ni)

x = − 1 , y = 1 , x=-1,y=1, x=1,y=1,代入即可得证 ∑ d ∣ n μ ( d ) = ∑ i = 0 k ( − 1 ) i C k i = ( 1 − 1 ) k = 0 \sum\limits_{d|n}μ(d)=\sum\limits^k_{i=0}(-1)^i C^i_{k}=(1-1)^k=0 dnμ(d)=i=0k(1)iCki=(11)k=0

由于莫比乌斯函数是积性函数,因此我们可以通过线性筛来求出莫比乌斯函数的值。

code

void gtmu(){
	mu[1]=1;
	for(int i=2;i<=n;i++){
	    if(!np[i]){
	        p[++p[0]]=i;
	        mu[i]=-1;
	    }
	    for(int j=1;j<=p[0]&&p[j]*i<=n;j++){
	        np[p[j]*i]=1;
	        if(i%p[j]==0){
	            mu[p[j]*i]=0;
	            break;
	        }
	        mu[p[j]*i]=-mu[i];
	    }
	}
}

莫比乌斯反演

公式1

F ( n ) = ∑ d ∣ n f ( d ) F(n)=\sum\limits_{d|n}f(d) F(n)=dnf(d),则有 f ( n ) = ∑ d ∣ n μ ( d ) F ( n d ) f(n)=\sum\limits_{d|n}μ(d)F(\frac{n}{d}) f(n)=dnμ(d)F(dn)

证明:

∑ d ∣ n μ ( d ) F ( n d ) = ∑ d ∣ n μ ( d ) ∑ k ∣ n d f ( k ) = ∑ k ∣ n f ( k ) ∑ d ∣ n k μ ( d ) = f ( n ) \sum\limits_{d|n}μ(d)F(\frac{n}{d})=\sum\limits_{d|n}μ(d)\sum\limits_{k|\frac{n}{d}}f(k)=\sum\limits_{k|n}f(k)\sum\limits_{d|\frac{n}{k}}μ(d)=f(n) dnμ(d)F(dn)=dnμ(d)kdnf(k)=knf(k)dknμ(d)=f(n)


公式2

F ( n ) = ∑ n ∣ d f ( d ) F(n)=\sum\limits_{n|d}f(d) F(n)=ndf(d),则有 f ( n ) = ∑ n ∣ d μ ( d n ) F ( d ) f(n)=\sum\limits_{n|d}μ(\frac{d}{n})F(d) f(n)=ndμ(nd)F(d)

证明:

∑ n ∣ d μ ( d n ) F ( d ) = ∑ n ∣ d μ ( d n ) ∑ d ∣ k f ( k ) = ∑ n ∣ k f ( k ) ∑ d ∣ k n μ ( d ) = f ( n ) \sum\limits_{n|d}μ(\frac{d}{n})F(d)=\sum\limits_{n|d}μ(\frac{d}{n})\sum\limits_{d|k}f(k)=\sum\limits_{n|k}f(k)\sum\limits_{d|\frac{k}{n}}μ(d)=f(n) ndμ(nd)F(d)=ndμ(nd)dkf(k)=nkf(k)dnkμ(d)=f(n)


以上两个公式的证明都用到了莫比乌斯函数的性质。


作用

对于一些函数 f ( n ) f(n) f(n),如果我们很难直接求出它的值,而容易求出倍数和或约数和 F ( n ) F(n) F(n),那么我们可以通过莫比乌斯反演求得 f ( n ) f(n) f(n)的值。

例: f ( n ) f(n) f(n)表示某一范围内 ( x , y ) = n (x,y)=n (x,y)=n的数对的数量, F ( n ) F(n) F(n)表示某一范围内 n ∣ ( x , y ) n|(x,y) n(x,y) 的数对的数量。那么直接求 f ( n ) f(n) f(n)并不是很好求,而 F ( n ) F(n) F(n)求起来相对简单一些,我们通过对 F ( n ) F(n) F(n)进行莫比乌斯反演来求得 f ( n ) f(n) f(n)


例题

洛谷P2257 YY的GCD

题目大意:求有多少数对 ( x , y ) (x,y) (x,y) ( 1 < = x < = n , 1 < = y < = m ) (1<=x<=n,1<=y<=m) (1<=x<=n,1<=y<=m)满足 g c d ( x , y ) gcd(x,y) gcd(x,y)为质数。

即求

∑ k = 1 n ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = = k ] ( k ∈ p r i m e ) \sum\limits^n_{k=1}\sum\limits^n_{i=1}\sum\limits^m_{j=1}[gcd(i,j)==k]\qquad(k\in prime) k=1ni=1nj=1m[gcd(i,j)==k](kprime)

两边同时除以 k k k,将 [ g c d ( i , j ) = = k ] [gcd(i,j)==k] [gcd(i,j)==k]化成 [ g c d ( i , j ) = = 1 ] [gcd(i,j)==1] [gcd(i,j)==1]

∑ k = 1 n ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ [ g c d ( i , j ) = = 1 ] ( k ∈ p r i m e ) \sum\limits^n_{k=1}\sum\limits^{⌊\frac{n}{k}⌋}_{i=1}\sum\limits^{⌊\frac{m}{k}⌋}_{j=1}[gcd(i,j)==1]\qquad(k\in prime) k=1ni=1knj=1km[gcd(i,j)==1](kprime)

我们知道莫比乌斯函数的性质

∑ d ∣ n μ ( d ) = [ n = = 1 ] \sum\limits_{d|n}μ(d)=[n==1] dnμ(d)=[n==1]

我们把 n n n换成 g c d ( i , j ) gcd(i,j) gcd(i,j),得 [ g c d ( i , j ) = = 1 ] = ∑ d ∣ g c d ( i , j ) μ ( d ) [gcd(i,j)==1]=\sum\limits_{d|gcd(i,j)}μ(d) [gcd(i,j)==1]=dgcd(i,j)μ(d)

原式变为

∑ k = 1 n ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ ∑ d ∣ g c d ( i , j ) μ ( d ) ( k ∈ p r i m e ) \sum\limits^n_{k=1}\sum\limits^{⌊\frac{n}{k}⌋}_{i=1}\sum\limits^{⌊\frac{m}{k}⌋}_{j=1}\sum\limits_{d|gcd(i,j)}μ(d)\qquad(k\in prime) k=1ni=1knj=1kmdgcd(i,j)μ(d)(kprime)

枚举 d d d

∑ k = 1 n ∑ d = 1 ⌊ n k ⌋ μ ( d ) ∗ ⌊ n k d ⌋ ∗ ⌊ m k d ⌋ ( k ∈ p r i m e ) \sum\limits^n_{k=1}\sum\limits^{⌊\frac{n}{k}⌋}_{d=1}μ(d)*⌊\frac{n}{kd}⌋*⌊\frac{m}{kd}⌋\qquad(k\in prime) k=1nd=1knμ(d)kdnkdm(kprime)

T = k d T=kd T=kd,有

∑ k = 1 n ∑ d = 1 ⌊ n k ⌋ μ ( d ) ∗ ⌊ n T ⌋ ∗ ⌊ m T ⌋ ( k ∈ p r i m e ) \sum\limits^n_{k=1}\sum\limits^{⌊\frac{n}{k}⌋}_{d=1}μ(d)*⌊\frac{n}{T}⌋*⌊\frac{m}{T}⌋\qquad(k\in prime) k=1nd=1knμ(d)TnTm(kprime)

枚举 T T T,提到前面

∑ T = 1 n ⌊ n T ⌋ ∗ ⌊ m T ⌋ ∑ k ∣ T , k ∈ p r i m e μ ( T k ) \sum\limits^n_{T=1}⌊\frac{n}{T}⌋*⌊\frac{m}{T}⌋\sum\limits_{k|T,k\in prime}μ(\frac{T}{k}) T=1nTnTmkT,kprimeμ(kT)

用数论分块处理即可,时间复杂度为 O ( n ln ⁡ n + T n ) O(n\ln n+T\sqrt n) O(nlnn+Tn )

code

#include
#define N 10000000
using namespace std;
int t,n,m,fl[N+5],p[N+5],mu[N+5],f[N+5];
long long ans,sum[N+5];
void dd(){
    mu[1]=1;
    for(int i=2;i<=N;i++){
        if(!fl[i]){
            p[++p[0]]=i;mu[i]=-1;
        }
        for(int j=1;j<=p[0]&&i*p[j]<=N;j++){
            fl[i*p[j]]=1;
            if(i%p[j]==0){
            	mu[i*p[j]]=0;
            	break;
            }
            mu[i*p[j]]=-mu[i];
        }
    }
    for(int i=1;i<=p[0];i++){
        for(int j=1;p[i]*j<=N;j++){
            f[p[i]*j]+=mu[j];
        }
    }
    for(int i=1;i<=N;i++){
        sum[i]=sum[i-1]+f[i];
    }
}
void ss(){
    ans=0;
    for(int l=1,r=0;l<=n;l=r+1){
        r=min(n/(n/l),m/(m/l));
        ans+=(sum[r]-sum[l-1])*(n/l)*(m/l);
    }
}
int main()
{
    dd();
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        if(n>m) swap(n,m);
        ss();
        printf("%lld\n",ans);
    }
    return 0;
}

你可能感兴趣的:(数论,c++,算法,开发语言)