莫比烏斯反演

前言

莫比烏斯反演是數論數學中很重要的內容,可以用於解決很多組合數學的問題。莫比烏斯反演的應用非常廣泛,內容很多但是結論卻並不複雜。
一道經典的莫比烏斯反演題:
求:i=1nj=1m[gcd(i,j)==d]\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)==d]
也就是說有多少對(i,j)(i,j)gcdgcddd


先知

常見積性函數1

1.σ(n)\sigma(n)——除數函數。用式子表示爲:σk(n)=dndk\sigma^k(n)=\sum_{d|n}d^k
2.d(n)d(n)——約數函數。表示n的約數的個數。用式子表示爲:σ(n)=dn1\sigma(n)=\sum_{d|n}1,也可寫作:d(n)=d=1n[dn]d(n)=\sum_{d=1}^n[d|n] (其實沒什麼太大區別)。
3.σ(n)\sigma(n)——約數和函數。用式子表示爲:σ(n)=dnd=d=1n[dn]d\sigma(n)=\sum_{d|n}d=\sum_{d=1}^n[d|n]⋅d
4.φ(n)\varphi(n)——歐拉函數。表示不大於n且與n互質的正整數個數,十分常見的數論函數。用式子表示:φ(n)=i=1n[gcd(n,i)=1]\varphi(n)=\sum_{i=1}^n[gcd(n,i)=1] 注意:n=1時,φ(n)=1\varphi(n)=1
5.μ(n)μ(n)——莫比烏斯函數2

常見完全積性函數

1.ϵ(n)ϵ(n)——元函數。也有人把它叫作e(n),我們只需要知道ϵ(n)=[n=1]ϵ(n)=[n=1]。([n=1][n=1]代表if(n==1) n=1; else n=0;)
2.I(n)I(n)——恆等函數。所謂恆等就是這個函數的值恆爲1。
3.id(n)id(n)——單位函數。id(n)=nid(n)=n
4.id(n)id(n)——冪函數。idk(n)=nkid^k(n)=n^k

PS:積性函數有一個特別重要的性質,那就是(積性函數∗積性函數)仍然爲積性函數!!!這個性質可以用來判斷能否被杜教篩!

接下來就到了狄利克雷卷積,似乎是很高深的東西


狄利克雷卷積3

定義:對於函數f,gf,g,定義它們的卷積爲(fg)(n)=dnf(d)g(nd)(f∗g)(n)=∑_{d|n}f(d)g({n\over d})(d|n代表d是n的因子 ),很明顯,所得也是一個數論函數,其中(fg)(f∗g)表示爲將ffgg,後面的括號代表範圍。(PS:後面的括號一般可以省略不寫,默認爲n)
很顯然,狄利克雷卷積滿足以下運算規律,可以類比爲乘法的運算法則:
交換律       (f∗g=g∗f);
結合律       ((f∗g)∗h=f∗(g∗h));
分配律       ((f+g)∗h=f∗h+g∗h);

任意函數卷積單位元仍爲它本身

不要小看元函數,它充當單位元,當元函數配合上結合律時還可以用來證明一些結論
d=11d=1∗1
σ=id1σ=id∗1
因爲      ϵ(n)=dnμ(d)ϵ(n)=∑_{d|n}μ(d)
所以      ϵ=1μϵ=1∗μ
因爲      φ(n)=dnμ(d)ndφ(n)=∑_{d|n}μ(d){n\over d}
所以      φ=μidφ=μ∗id
因爲      n=dnφ(d)n=∑_{d|n}φ(d)
所以      id=φ1id=φ∗1

莫比烏斯函數μμ

莫比烏斯反演定理形式一:
F(n)=dnf(d)=>f(n)=dnμ(d)F(nd)F(n)=∑_{d|n}f(d)=>f(n)=∑_{d|n}μ(d)F({n\over d})
證明:
變形得到:
f(n)=dnμ(d)F(nd)=dnμ(d)kndf(k)=knf(k)dnkμ(d)f(n)=∑_{d|n}μ(d)F({n\over d})=∑_{d|n}μ(d)∑_{k|{n\over d}}f(k)=∑_{k|n}f(k)∑_{d|{n\over k}}μ(d)
因爲
dnμ(d)={1,n=10,n>1∑_{d|n}μ(d)= \begin{cases} 1,n=1\\ 0,n>1\\ \end{cases}
所以當且僅當nk=1{n\over k}=1,即n=kn=kdnkμ(d)=1∑_{d|{n\over k}}μ(d)=1,其餘時間爲0。

knf(k)dnkμ(d)=f(n)∑_{k|n}f(k)∑_{d|{n\over k}}μ(d)=f(n)
莫比烏斯反演定理形式二:
F(n)=ndf(d)=>f(n)=ndμ(dn)F(d)F(n)=∑_{n|d}f(d)=>f(n)=∑_{n|d}μ({d\over n})F(d)
證明:
k=dnk={d\over n},得到
f(n)=k=1+μ(k)F(nk)=k=1+μ(k)nktf(t)=ntf(t)ktnμ(k)f(n)=∑_{k=1}^{+\infty}μ(k)F({nk})=∑_{k=1}^{+\infty}μ(k)∑_{nk|t}f(t)=∑_{n|t}f(t)∑_{k|{t\over n}}μ(k)
所以當且僅當tn=1{t\over n}=1,即t=nt=nktnμ(k)=1∑_{k|{t\over n}}μ(k)=1,其餘時間爲0。

ntf(t)ktnμ(k)=f(n)∑_{n|t}f(t)∑_{k|{t\over n}}μ(k)=f(n)
證畢。

歐拉函數 φφ

歐拉函數爲積性函數(若mnm、n互質,有φ(m)φ(n)=φ(mn)φ(m)φ(n) = φ(mn))
歐拉函數φ(n)定義爲,1~n中與n的最大公約數爲1的數字的個數。例如 φ(5) = 4, φ(6) = 2
  若pp爲質數,顯然 φ(p)=p1φ(p) = p-1
  若n=pkn=p^k, 則n的大於1的約數有p,2p,3p,...(pk12)p,(pk11)pp, 2p, 3p,...(p^{k-1}-2)p, (p^{k-1}-1)ppk1p^{k-1}個數。所以φ(n)=pkpk1φ(n) = p^k-p^{k-1}
歐拉函數有一個很著名的性質:dnφ(d)=n∑_{d|n}φ(d)=n
因爲
在這裏插入圖片描述
所以對於任意
在這裏插入圖片描述
或者寫成這種形式:
在這裏插入圖片描述 
莫比烏斯函數和歐拉函數的關係:
在這裏插入圖片描述


杜教篩

考慮如何求μ的前綴和
比如說101010^{10}? 線篩會T。這時我們就需要杜教篩了。
杜教篩是以低於線性的時間複雜度來計算積性函數的前綴和的神奇篩法!
即我們需要計算的式子爲:i=1nf(i)∑_{i=1}^nf(i)(f(i)f(i)爲積性函數)

杜教篩的套路式

我們構造兩個積性函數hhgg。使得h=fgh=f∗g。記S(n)=i=1nf(i)S(n)=∑_{i=1}^nf(i)
i=1nh(i)=i=1ndig(d)f(id)∑_{i=1}^nh(i)=∑_{i=1}^n∑_{d|i}g(d)f({i\over d})
d=1ng(d)i=1[nd]f(i)→∑_{d=1}^ng(d)∑_{i=1}^{[{n\over d}]}f(i)
i=1nh(i)=d=1ng(d)S(nd)→∑_{i=1}^nh(i)=∑_{d=1}^ng(d)∗S(⌊{n\over d}⌋)
接着,我們將右邊式子的第一項給提出來,可以得到:
i=1nh(i)=g(1)S(n)+d=2ng(d)S(nd)∑_{i=1}^nh(i)=g(1)∗S(n)+∑_{d=2}^ng(d)∗S(⌊{n\over d}⌋)
g(1)S(n)=i=1nh(i)d=2ng(d)S(nd)→g(1)∗S(n)=∑_{i=1}^nh(i)-∑_{d=2}^ng(d)∗S(⌊{n\over d}⌋)
其中的h(i)=(fg)(i)h(i)=(f∗g)(i)
經各種分析,只要當你的h(i)h(i)的前綴和很好求,能在較短的時間內求出,那麼當我們對後面的式子進行整除分塊時,求S(n)S(n)的複雜度爲O(n23)O(n^{2\over 3})。對於gghh需要從我們對狄利克雷卷積中的各種式子的熟悉和仔細觀察式子的能力中得到。

應用

一:求S(n)=i=1nμ(i)S(n)=∑_{i=1}^nμ(i)
根據那個套路式:g(1)S(n)=i=1n(fg)(i)d=2ng(d)S(nd)g(1)S(n)=∑_{i=1}^n(f∗g)(i)−∑_{d=2}^ng(d)⋅S(⌊{n\over d}⌋),我們只需要找一個積性函數gg使得這個函數與μ的卷積的前綴和容易求。如果你認真的看了上文,應該就可以很輕鬆的想到一個積性函數II
我們知道μI=ϵμ∗I=ϵ,很顯然,單位元的前綴和非常好求,就是1,並且II十分方便整除分塊。所以我們把這個積性函數帶入上述式子中可以得到:
S(n)=1d=2nS(nd)S(n)=1−∑_{d=2}^nS(⌊{n\over d}⌋)
這就是杜教篩莫比烏斯函數的前綴和。
二:求S(n)=i=1nφ(i)S(n)=∑_{i=1}^nφ(i)
與求莫比烏斯函數的思路類似。
我們在腦海中找到一個與歐拉函數有關的卷積式子:φI=idφ∗I=id
我們可以發現,在篩歐拉函數前綴和所選擇的積性函數g同樣也是I喲!代入得:
S(n)=i=1nid=2nS(nd)S(n)=∑_{i=1}^ni−∑_{d=2}^nS(⌊{n\over d}⌋)
前面那個式子可以利用等差數列求和公式O(1)O(1)的計算出結果,後面同樣利用整除分塊。
所以,我們又學會了如何篩歐拉函數的前綴和啦!
三:求S(n)=i=1niφ(i)S(n)=∑_{i=1}^ni⋅φ(i)
這個式子是不是無法一眼看出需要配什麼積性函數了呢?
我們考慮狄利克雷卷積的形式:dn(dφ(d))g(nd)∑_{d|n}(d⋅φ(d))⋅g({n\over d})
我們看前面這個dd不太爽,考慮後面配出一個積性函數使得這個dd能夠被約掉。因此,我們嘗試將gg配成idid。這樣就可以把dd給弄沒!代入得:
dn(dφ(d))nd=dnnφ(d)∑_{d|n}(d⋅φ(d))⋅{n\over d}=∑_{d|n}n⋅φ(d)=ndnφ(d)=n2→=n∑_{d|n}φ(d)=n^2
我們驚喜的發現,似乎配對了!!!
得:
S(n)=i=1ni2d=2ndS(nd)S(n)=∑_{i=1}^ni^2−∑_{d=2}^nd⋅S(⌊{n\over d}⌋)
對於這個式子,我們前面可以利用平方和的公式O(1)O(1)算出結果,後面的式子利用等差數列求和公式進行整除分塊。

我們可以通過以上的思路求得這個看似無法篩的積性函數的前綴和。

代碼實現
我們首先先線篩出數據範圍根號左右的積性函數的前綴和。再遞歸的實現杜教篩。特別要注意的是,杜教篩篩出的前綴和一定要存下來!!!
如果你比較的勤勞,那就去手寫hash,如果你想偷懶,那就最好用stl中的unordered_map,最好不要用map,平白無故多個log的複雜度,何必呢…
還有一點,一定要記得取模!!!以及,判斷要不要開long long,搞不好你TLE就是因爲取模去多了,或者long long開多啦!

代碼如下:

#include<bits/stdc++.h>
using namespace std;
const int maxx = 10000001 * 2;
bool isprime[maxx];
int prime[maxx/10];
int mu[maxx];
int countp;
map<long long,int> mp;
void Get_mu(int maxn)  //求莫比烏斯函數
{
    memset(isprime,1,sizeof(isprime));
    isprime[1] = true;
    mu[1] = 1;
    for(int i=2; i<=maxn; i++)
    {
        if(isprime[i])
            prime[++countp] = i, mu[i] = -1;
        for(int j=1; i*prime[j]<=maxn&&j<=countp; j++)
        {
            int t = i * prime[j];
            isprime[t] = false;
            if(!(i%prime[j]))
            {
                mu[t] = 0;
                break;
            }
            else mu[t] = -mu[i];
        }
    }
}
long long n,m;
long long nn,top;
long long ans;
int get(long long x)
{
    int sum = 0;
    for(long long i=2; i<=x; i++)
    {
        long long zz = x/i;
        long long next = x/zz;
        if(zz <= top)
            sum += (next-i+1) * mu[zz];
        else
        {
            if(mp[zz])
                sum += (next-i+1) * (mp[zz]);
            else
                sum += (next-i+1) * get(zz);
        }
        i = next;
    }
    if(x>top)
        mp[x] = (1-sum);
    return (1-sum);
}

int main()
{
    cin>>n>>m;
    top = maxx-1;
    Get_mu(maxx-1);
    for(int i=1; i<=top; i++)
        mu[i]+=mu[i-1];
    ans = get((long long)m) - get((long long)(n-1));
    cout<<ans<<endl;
}


莫比烏斯函數

莫比烏斯函數是一個由容斥係數所構成的函數。

μ(d)μ(d)的定義是:

  • d=1d=1時,μ(d)=1μ(d)=1
  • d=Πi=1kpid=Π_{i=1}^kp_ipip_i爲互異素數時,μ(d)=(1)kμ(d)=(−1)^k。(說直白點,就是dd分解質因數後,沒有冪次大於平方的質因子,此時函數值根據分解的個數決定);
    只要當dd含有任何質因子的冪次大於2,則函數值爲0.

    μ(x)={1x=10x1xx1xμ(x)= \begin{cases} 1,x=1\\ 0,x存在平方因子\\ -1,x有奇數個質因子(包括x是質數)\\ 1,x有偶數個質因子\\ \end{cases}
    當然,莫比烏斯函數也有很多有趣的性質:
  • 對於任意正整數nndnμ(d)=[n=1]∑_{d|n}μ(d)=[n=1]。[n=1][n=1]表示只有當n=1n=1成立時,返回值爲1;否則,值爲0;(這個就是用μμ是容斥係數的性質可以證明)(PS:這一條性質是莫比烏斯反演中最常用的)
  • 對於任意正整數n,∑d|nμ(d)d=ϕ(n)n。(這個性質很奇妙,它把歐拉函數和莫比烏斯函數結合起來,或許我之後寫杜教篩的學習筆記時會去證明吧)

程序實現並不難,求μ(x)μ(x)

  1. 打表:
//線性篩法求莫比烏斯函數
bool check[MAX+10];
int prime[MAX+10];
int mu[MAX+10];
void Moblus()
{
    memset(check,false,sizeof(check));
    mu[1] = 1;
    int tot = 0;
    for(int i = 2; i <= MAX; i++)
    {
        if( !check[i] )
        {
            prime[tot++] = i;
            mu[i] = -1;
        }
        for(int j = 0; j < tot; j++)
        {
            if(i * prime[j] > MAX)
                break;
            check[i * prime[j]] = true;
            if( i % prime[j] == 0)
            {
                mu[i * prime[j]] = 0;
                break;
            }
            else
            {
                mu[i * prime[j]] = -mu[i];
            }
        }
    }
}
  1. 非打表:
ll getmob(ll a)
{
    ll x=a,tmp=a;
    int cnt=0,now=0;
    for(ll j=2; j*j<=x; j++)
    {
        now=0;
        if(x%j==0)
        {
            while(x%j==0)
                now++,x/=j;
            if(now>1)
                return 0;
            cnt++;
        }
    }
    if(x!=1)
        cnt++;
    return (cnt&1)?-1:1;
}

莫比烏斯反演

莫比烏斯反演是數論中的重要內容,在許多情況下能夠簡化運算。

我們考慮以下列函數:
F(n)=dnf(d)F(n)=\sum_{d|n}f(d)
可推導得:
f(n)=dnμ(d)F(nd)f(n)=\sum_{d|n}μ(d)F(⌊{n\over d}⌋)
這就稱作莫比烏斯反演定理。

莫比烏斯反演證明

莫比烏斯反演的證明有兩種方式。
定義證明方法:
dnμ(d)F(nd)\sum_{d|n}μ(d)F(⌊{n\over d}⌋)
=dnμ(d)indf(i)1=\sum_{d|n}μ(d)\sum_{i|⌊{n\over d}⌋}f(i)(1)
=inf(i)dniμ(d)2=\sum_{i|n}f(i)\sum_{d|⌊{n\over i}⌋}μ(d)(2)
ni=1{n\over i}=1,即n=in=i時,(2)式纔不爲0。所以(2)式只剩下f(n)f(n)一項了。
=f(n)=f(n)
莫比烏斯反演還有另外的一種形式,當F(n)和f(n)滿足:
F(n)=ndf(d)F(n)=\sum_{n|d}f(d)
可以推出:
f(n)=ndμ(dn)F(d)f(n)=\sum_{n|d}μ({d\over n})F(d)

莫比烏斯反演公式總結

約數的莫比烏斯反演:
若:f(n)=dng(d)f(n)=\sum_{d|n}g(d)
則:g(n)=dnμ(d)f(nd)g(n)=\sum_{d|n}μ(d)f({n\over d})
倍數的莫比烏斯反演:
若:f(n)=ndg(d)f(n)=\sum_{n|d}g(d)
則:g(n)=ndμ(dn)f(d)g(n)=\sum_{n|d}μ({d\over n})f(d)


借鑑自:https://www.cnblogs.com/peng-ym/p/8647856.html


  1. [積性函數百度百科]
    (https://baike.baidu.com/item/積性函數/8354949?fr=aladdin) ↩︎

  2. 莫比烏斯百度百科 ↩︎

  3. [狄利克雷卷積百度百科]
    (https://baike.baidu.com/item/狄利克雷乘積/18903903?fr=aladdin) ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章