快樂地打牢基礎(14)——莫比烏斯反演

數論千萬條,反演第一條。反演不會做,隊友兩行淚。

一、什麼是莫比烏斯反演?

  • g(n)=dnf(d)f(n)=dnμ(d)g(nd).............(1){g(n) = \displaystyle\sum_{d|n}f(d)\Longleftrightarrow f(n) = \displaystyle\sum_{d|n}\mu(d)g(\frac{n}{d})}.............(1)
  • g(n)=ndf(d)f(n)=ndμ(dn)g(d)..............(2){g(n) = \displaystyle\sum_{n|d}f(d)\Longleftrightarrow f(n) = \displaystyle\sum_{n|d}\mu(\frac{d}{n})g(d)}..............(2)

很多時候函數ff很難求,但是函數gg可以比較容易的求出來,所有我們通過求出gg來求出ff,這個由gg求出ff的過程就是反演。

二、前置知識


1.莫比烏斯函數

μ(n)={1,          n=1(1)k,  n=P1P2...Pk0,          other\mu(n) =\begin{cases} 1,\ \ \ \ \ \ \ \ \ \ n=1\\ (-1)^k,\ \ n = P_1P_2...P_k\\0,\ \ \ \ \ \ \ \ \ \ other\end{cases}
其中P1P2...PkP_1P_2...P_k爲質數。

莫比烏斯函數推導

線性篩求莫比烏斯函數:

int prime_tot = 0;
bool prime_tag[N];
int prime[N],mu[N];

void get_prime(){
    mu[1] = 1;//n = 1時,莫比烏斯函數mu[1] = 1,
    for(int i = 2; i < N; i++){
        if(!prime_tag[i]) prime[prime_tot++] = i,mu[i] = -1;//如果i是一個質數,那麼其莫比烏斯函數一定是-1
        for(int j = 0; j < prime_tot && i * prime[j] < N; j++){
            prime_tag[i * prime[j]] = true;
            if(i % prime[j] == 0){
                mu[i * prime[j]] = 0;//可以知道此處prime[j] | i,
                					//那麼i * prime[j]裏就有一個prime[j]的平方存在
                break;
            }else
                mu[i * prime[j]] = -mu[i];//i * prime[j]爲k個質數的乘積,如果k是奇數mu[i]就是-1,
                						//是偶數mu[i]爲1
        }
    }
}

2.狄利克雷卷積

狄利克雷卷積是一個對函數的運算。

狄利克雷卷積:
對於兩個函數f,gf,g,它們的狄利克雷卷積是

(fg)(n)=dnf(d)g(nd)(f*g)(n) = \displaystyle\sum_{d|n}f(d)g(\frac{n}{d})

積性函數:
兩個數a,ba,b互質,對於函數ff,如果f(ab)=f(a)f(b)f(ab)=f(a)f(b),那麼函數ff就是一個積性函數。

完全積性函數:
任意兩個數a,ba,b,都有f(ab)=f(a)f(b)f(ab)=f(a)f(b)

常見的積性函數

  • 歐拉函數φ(n)\varphi(n)
  • 莫比烏斯函數μ(n)\mu(n)
  • 單位函數 Id(n)=nId(n) = n
  • 不變函數1(n)=11(n) = 1,不變的函數,所有值都是11
  • 冪函數idk(k)=nkidk(k) = n^k
  • 因子個數函數d(n),d=1(n)1(n)d(n),d = 1(n)*1(n),n的正因子數目
  • 因子和函數σ(n),σ=1(n)Idn\sigma(n),\sigma = 1(n)*Id,n的所有正因子之和
  • 因子函數σk(n)σk(n),n的所有正因子的k次冪之和
  • 狄利克雷卷積單位元ε=[n==1]\varepsilon = [n==1]
  • 逆元:對於每一個f(1)=f(1)=\not0的函數ff,都有fg=εf∗g=\varepsilon

如何求一個函數的逆元:
首先我們定義兩個函數f,gf,g
g(n)=1f(1)([n==1]in,i1f(i)g(ni))g(n)=\frac{1}{f(1)}\left([n==1]-\sum_{i|n,i\neq 1}f(i)g(\frac{n}{i})\right)
這樣的話,他們的狄利克雷卷積 fgf*g 就是:
inf(i)g(ni)                                =f(1)g(n)+in,i1f(i)g(ni)                                                                                        =f(1)1f(1)([n==1]in,i1f(i)g(ni))+in,i1f(i)g(ni)=[n==1]\sum_{i|n}f(i)g(\frac{n}{i})\\\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =f(1)g(n)+\sum_{i|n,i\neq1}f(i)g(\frac{n}{i})\\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =f(1)*\frac{1}{f(1)}\left([n==1]-\sum_{i|n,i\neq 1}f(i)g(\frac{n}{i})\right)+ \sum_{i|n,i\neq1}f(i)g(\frac{n}{i})\\=[n==1]
此處證明推導均來自:鈴懸dalao的博客

一些關於莫比烏斯函數和狄利克雷卷積單位元的性質

1.不變常數 11 和莫比烏斯函數 μ\mu 互爲逆元。

用上述求逆元的方法直接套,令g(n)=1(n),f(n)=μ(n)g(n) = 1(n),f(n) = \mu(n)

2.兩個積性函數的狄利克雷卷積是積性函數。

3.積性函數的逆是積性函數。

2和3具體詳細的證明還是參考鈴懸dalao的博客https://www.luogu.org/blog/lx-2003/mobius-inversion

3.整除分塊

看一個題目:求k=1nnk\displaystyle\sum^{n}_{k= 1}\lfloor\frac{n}{k}\rfloor的值。
可能會想到暴力,直接遍歷一遍,但當nn很大的時候,時間是使dalao們不滿意的。
所以有了整除分塊的想法。
n=25n = 25 來舉例:
首先可以發現,  n  k \lfloor \frac{\ n\ }{\ k\ }\rfloor 只有2n2\sqrt{n}種,那我們按照  n  k \lfloor \frac{\ n\ }{\ k\ }\rfloor 的結果分類的:
在這裏插入圖片描述

int ans = 0;
for(int l = 1 , r; l <= n; l = r + 1){
	r = n / (n / l);
	ans += (r - l + 1)(n / l);
}

這樣一來,整除通過這種分塊的思想就把時間複雜度降到了O(2n)O(2\sqrt{n})

三、莫比烏斯反演的證明


  • g(n)=dnf(d)f(n)=dnμ(d)g(nd).............(1){g(n) = \displaystyle\sum_{d|n}f(d)\Longleftrightarrow f(n) = \displaystyle\sum_{d|n}\mu(d)g(\frac{n}{d})}.............(1)
  • g(n)=ndf(d)f(n)=ndμ(dn)g(d)..............(2){g(n) = \displaystyle\sum_{n|d}f(d)\Longleftrightarrow f(n) = \displaystyle\sum_{n|d}\mu(\frac{d}{n})g(d)}..............(2)

首先證明(1)(1),這很好證明(11代表不變函數):
g=f1,f=μg=μ1f=fg = f*1,f = \mu*g=\mu *1*f=f
然後證明(2)(2)
k=dnk = \frac{d}{n},則:
ndμ(dn)g(d)=kμ(k)g(nk)=kμ(k)(nk)tf(t)\sum_{n|d}\mu(\frac{d}{n})g(d)=\sum_{k}\mu(k)g(nk)=\sum_{k}\mu(k)\sum_{(nk)|t}f(t)
tf(t)(nk)tμ(k)=tf(t)ε(tn)=f(n){\displaystyle \sum_{t}f(t)\sum_{(nk)|t}\mu(k)=\sum_{t}f(t)\varepsilon(\frac{t}{n})=f(n)}

四、一點點題目


注:所有例題中gcd(x,y)gcd(x,y)都爲x,yx,y的最大公約數。

【例1】luogu P2522 [HAOI2011]Problem b
題意

對於給定的TT個詢問,每次求友多少個數對(x,y)(x,y)滿足axb,cyda\leq x\leq b,c\leq y\leq d,且gcd(x,y)=kgcd(x,y) = k

思路
首先可以將問題使用容斥原理轉化一下:

定義solve(b,d)solve(b,d)爲數對(x,y)(x,y)是滿足1xb,1yd1\leq x\leq b,1\leq y\leq d,且gcd(x,y)=kgcd(x,y)=k的個數。

根據容斥原理:

ans=solve(b,d)solve(a1,d)solve(b,c1)+solve(a1,c1)ans = solve(b,d) - solve(a-1,d) - solve(b,c-1) + solve(a-1,c-1)

這樣就可以利用一種類似於前綴和的方法求出來答案。

問題就轉化爲求出1xbk,1ydk1\leq x\leq \lfloor\frac{b}{k}\rfloor,1\leq y\leq \lfloor\frac{d}{k}\rfloor,且gcd(x,y)=1gcd(x,y)=1的數對個數。

下面利用莫比烏斯反演,來解題:

首先設
f(i)=x=1ny=1m[gcd(x,y)==i]f(i) = \displaystyle\sum_{x=1}^{n}\sum_{y=1}^{m}[gcd(x,y) == i]

g(i)=x=1ny=1m[i  gcd(x,y)]=nimig(i) = \displaystyle\sum_{x=1}^{n}\sum_{y = 1}^{m}[i\ |\ gcd(x,y)]=\lfloor\frac{n}{i}\rfloor\lfloor\frac{m}{i}\rfloor

f(i)=iqμ(qi)g(q)=iqμ(qi)nqmqf(i) = \displaystyle\sum_{i|q }\mu(\frac{q}{i})g(q)= \displaystyle\sum_{i|q }\mu(\frac{q}{i})\lfloor\frac{n}{q}\rfloor\lfloor\frac{m}{q}\rfloor

通過之前推導出的紅字,可以知道現在需要的就是求出f(1)f(1),將i=1n=bkm=dki = 1,n = \lfloor\frac{b}{k}\rfloor,m= \lfloor\frac{d}{k}\rfloor代入,可以得到:

f(1)=1qμ(q1)g(q)=1qμ(q1)bqkdqkf(1) = \displaystyle\sum_{1|q }\mu(\frac{q}{1})g(q)= \displaystyle\sum_{1|q }\mu(\frac{q}{1})\lfloor\frac{b}{qk}\rfloor\lfloor\frac{d}{qk}\rfloor

然後使用分塊處理可得到答案。

//莫比烏斯反演例題
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cctype>
#define ll long long
using namespace std;

const int N = 5e4 + 10;
bool prime_tag[N] = {0};
int prime[N],mu[N],prime_tot = 0;
ll sum[N] = {0};
int cas,a,b,c,d,k;

void get_mu(){
    mu[1] = 1;
    for(int i = 2; i < N; i++){
        if(!prime_tag[i]){
            prime[prime_tot++] = i;
            mu[i] = -1;
        }
        for(int j = 0; j < prime_tot && i * prime[j] < N; j++){
            prime_tag[i * prime[j]] = true;
            if(i % prime[j] == 0){
                 mu[i * prime[j]] = 0;
                 break;
            }else{
                mu[i * prime[j]] = -mu[i];
            }
        }
    }
    sum[0] = 0;
    for(int i = 1; i < N; i++)
        sum[i] = sum[i - 1] + mu[i];
}
ll solve(ll b ,ll d){
    b = b / k;
    d = d / k;
    ll res = 0;
    int t = min(b,d);
    for(int l = 1,r; l <= t; l = r + 1){
        r = min((ll)b / (b / l),(ll)d / (d / l));
        res += (sum[r] - sum[l - 1]) * (b / l ) * (d / l);
    }
    return res;
}
int main(){
    get_mu();
    //read(cas);
    scanf("%d",&cas);
    while(cas--){
        //read(a);read(b);read(c);read(d);read(k);
        scanf("%d %d %d %d %d",&a,&b,&c,&d,&k);
        //printf("%d %d %d %d %d\n",a,b,c,d,k);
        printf("%lld\n",solve(b,d) - solve(a-1,d) - solve(b,c-1) + solve(a-1,c-1));
    }
    return 0;
}

【例2】luogu P2257 YY的GCD
題意
給定NMN,M,求1xN,1yM1\leq x \leq N,1\leq y \leq Mgcd(x,y)gcd(x,y)爲質數的(x,y)(x,y)有多少對?
思路
和上一題很像,區別在於要確保gcd(x,y)==k,kgcd(x,y) == k,k是一個質數。
f(x)=xprimex  dμ(dx)g(d)f(x) = \displaystyle\sum_{x\in prime}\sum_{x\ | \ d}\mu(\frac{d}{x})g(d)

         =d=1min(n,m)ndmdxprime,x  dμ(dx)\ \ \ \ \ \ \ \ \ =\displaystyle\sum_{d = 1}^{min(n,m)}\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor\sum_{x\in prime ,x\ |\ d}\mu(\frac{d}{x})

這裏我們可以令:
sum[d]=xprime,x  dμ(dx)sum[d] = \displaystyle\sum_{x\in prime ,x\ |\ d}\mu(\frac{d}{x})

這樣一來:
f(x)=xprimex  dμ(dx)g(d)f(x) = \displaystyle\sum_{x\in prime}\sum_{x\ | \ d}\mu(\frac{d}{x})g(d)

         =d=1min(n,m)ndmdsum[d]\ \ \ \ \ \ \ \ \ =\displaystyle\sum_{d = 1}^{min(n,m)}\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor sum[d]

預處理代碼:

    sum[0] = 0;
    for(int i = 0 ; i < prime_tot; i++){
        for(int j  = 1; prime[i] * j < N; j++){
            sum[prime[i] * j] += mu[j];
        }
    }
    for(int i = 1 ; i < N; i++)
        sum[i] += sum[i-1] + sum[i];

提前預處理這個sum(d)sum(d),再求一個前綴和就可以很好的放在分塊中解決

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;

const int N = 1e7 + 7;
int prime[N],prime_tot = 0,mu[N];
ll sum[N] = {0};
bool prime_tag[N] = {0};
int cas,n,m;

void get_mu(){
    mu[1] = 1;
    for(int i = 2; i < N; i++){
        if(!prime_tag[i]){
            prime[prime_tot++] = i;
            mu[i] = -1;
        }
        for(int j = 0 ; j < prime_tot && i * prime[j] < N; j++){
            prime_tag[i * prime[j]] = true;
            if(i % prime[j] == 0){
                mu[i * prime[j]] = 0;
                break;
            }
                mu[i * prime[j]] = -mu[i];
        }
    }
    sum[0] = 0;
    for(int i = 0 ; i < prime_tot; i++){
        for(int j  = 1; prime[i] * j < N; j++){
            sum[prime[i] * j] += mu[j];
        }
    }
    for(int i = 1 ; i < N; i++)
        sum[i] += sum[i-1] + sum[i];
}
ll solve(){
    ll res = 0,res1 = 0;
    for(int l = 1,r; l <= n; l = r + 1){
        r = min(n / (n / l),m / (m / l));
        res += (ll) (sum[r] - sum[l - 1]) * (n / l) * (m / l);
    }

    return res / 2;
}
int main(){
    get_mu();
    scanf("%d",&cas);
    while(cas--){
        scanf("%d %d",&n,&m);
        if(n > m) swap(n,m);
        printf("%lld\n",solve());

    }
    return 0;
}

【例3】luogu P4449 於神之怒加強版
題意
給定n,m,kn,m,k,計算i=1nj=1mgcd(i,j)k mod(109+7)\displaystyle\sum_{i = 1}^{n}\sum_{j = 1}^{m}gcd(i,j)^k\ mod(10^9+7)的值。
思路
枚舉最大公因數 dd,並計算最大公因數爲 dd 的數對個數i=1nj=1m[gcd(i,j)==d]\displaystyle\sum_{i = 1}^{n}\sum_{j = 1}^{m}[gcd(i,j)==d]的值
那麼答案就是 dmin(n,m)d×dk\displaystyle\sum_d^{min(n,m)}最大公因數爲 d的數對個數\times d^k
我們使用莫比烏斯反演:
f(u)=i=1nj=1m[gcd(i,j)==u]........(1)g(u)=i=1nj=1m[ugcd(i,j)]=numu........(2)f(u) = \displaystyle\sum_{i = 1}^{n}\sum_{j = 1}^{m}[gcd(i,j)==u]........(1) \\g(u) = \displaystyle\sum_{i = 1}^{n}\sum_{j = 1}^{m}[u|gcd(i,j)] = \lfloor\frac{n}{u}\rfloor\lfloor\frac{m}{u}\rfloor........(2)

f(u)=upμ(pu)g(p)f(u) = \displaystyle\sum_{u|p}\mu(\frac{p}{u})g(p)
由於
i=1nj=1m[gcd(i,j)==d]\displaystyle\sum_{i = 1}^{n}\sum_{j = 1}^{m}[gcd(i,j)==d]i=1ndj=1md[gcd(i,j)==1]\displaystyle\sum_{i = 1}^{\frac{n}{d}}\sum_{j = 1}^{\frac{m}{d}}[gcd(i,j)==1]是等價的

(1)(2)(1)(2)中的n=nd,m=nd,u=1n = \lfloor\frac{n}{d}\rfloor,m = \lfloor\frac{n}{d}\rfloor,u = 1

f(1)=pμ(p1)nd×pmd×pf(1) = \displaystyle\sum_{p}\mu(\frac{p}{1})\lfloor\frac{n}{d\times p}\rfloor\lfloor\frac{m}{d\times p}\rfloor(注意此時nd×p\lfloor\frac{n}{d\times p}\rfloor中的nd\lfloor\frac{n}{d}\rfloor是常量,是不變換的)

ans=ddkpμ(p)ndpmdpans = \displaystyle\sum_dd^k\displaystyle\sum_{p}\mu(p)\lfloor\frac{n}{ dp}\rfloor\lfloor\frac{m}{ dp}\rfloor
爲了使形式更加明顯一些,設Q=dpQ = dp

ans=QnQmQd  Qdkμ(Qd)ans = \displaystyle\sum_Q\displaystyle\lfloor\frac{n}{ Q}\rfloor\lfloor\frac{m}{ Q}\rfloor \sum_{d\ |\ Q}d^k\mu(\frac{Q}{d})

到這裏我們設F(Q)=d  Qdkμ(Qd)F(Q) = \displaystyle \sum_{d\ |\ Q}d^k\mu(\frac{Q}{d}),可以很(bu)容易發現F(Q)F(Q)是一個狄利克雷卷積的形式。
順便再來複習狄利克雷卷積的定義:

(fg)(n)=dnf(d)g(nd)(f*g)(n) = \displaystyle\sum_{d|n}f(d)g(\frac{n}{d})

那麼F=idkuF = idk*u

我們的答案就變成了:

ans=QnQmQF(Q)ans = \displaystyle\sum_Q\displaystyle\lfloor\frac{n}{ Q}\rfloor\lfloor\frac{m}{ Q}\rfloor F(Q)

前一部分直接使用分塊可以很好的求出,F(Q)F(Q)則需要使用線性篩來預處理,並求出前綴和。

根據狄利克雷卷積的性質,因爲 idkidkμ\mu 都是積性函數所以FF也是積性函數,那麼FF就可以像φ\varphi一樣利用F(a×b)=F(a)×F(b)F(a\times b) = F(a)\times F(b)求出。

對於F(Q)=d  Qdkμ(Qd)F(Q) = \displaystyle \sum_{d\ |\ Q}d^k\mu(\frac{Q}{d}),將Q按唯一分解定理分解:
Q=p1c1p2c2...pmcmQ = p_1^{c1}p_2^{c2}...p_m^{cm}

F(Q)=i=1mF(pici)........(1)F(Q) = \displaystyle\prod_{i =1}^m F(p_i^{ci})........(1)

同時,對於F(pici)F(p_i^{ci}),因爲莫比烏斯函數的性質,μ(prime)=1,μ(1)=1\mu(prime)=-1,\mu(1)=1,所以只有在 d=pici1d = p_i^{ci-1}d=picid = p_i^{ci} 時對d  picidkμ(picid)\displaystyle \sum_{d\ |\ p_i^{ci}}d^k\mu(\frac{p_i^{ci}}{d})有貢獻。所以,(1)(1)可以轉化爲:

F(Q)F(Q)
=i=1m(pik×(ci1)×μ(pi) + pik×ci×μ(1))\displaystyle=\prod_{i=1}^{m}(p_i^{k\times (ci-1)}\times \mu(p_i)\ +\ p_i^{k\times c_i}\times \mu(1))

=i=1mpik×(ci1)×(pik1)\displaystyle =\prod_{i=1}^{m}p_i^{k\times (ci-1)}\times(p_i^{k}-1)

prime[j] prime[j] \ |\not i的時候,兩者互質,滿足積性函數的性質,f[iprime[j]]=f[i]f[prime[j]]f[i * prime[j]] = f[i] * f[prime[j]]
prime[j]  iprime[j] \ |\ i的時候,f[iprime[j]]=f[i]prime[j]kf[i * prime[j]] = f[i] * prime[j]^k

第二個結論和篩φ\varphi函數的時候類似,下面證明一下:
p=prime[j]p = prime[j]
p[j]  ip[j] \ |\ i時,證明 ip[j]\frac{i}{p[j]}ii有相同的質因子,那麼

F(i)F(ip)=pik(ci1)×pik1...pik(ci2)×pik1...=pk\frac{F(i)}{F(\frac{i}{p})}=\frac{p_i^{k{(ci-1)}}\times p_i^k-1...}{p_i^{k{(ci-2)}}\times p_i^k-1...}=p^k

所以,f[iprime[j]]=f[i]prime[j]kf[i * prime[j]] = f[i] * prime[j]^k

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;

const int N = 5e6 + 10;
const int mod = 1e9 + 7;
ll prime[N],mu[N],tot = 0,f[N] ={0},g[N] = {0};
bool prime_tag[N] = {0};
int t,k,n,m;
ll qpow(ll a,ll b){
    ll res = 1ll;
    while(b){
        if(b & 1){
            res = res * a % mod;
        }
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}
void init(){
    f[1] = 1;
    for(int i = 2; i < N; i++){
        if(!prime_tag[i]){
            prime[tot] = i;
            g[tot] = qpow(i,k);
            f[i] = (g[tot]-1 + mod) % mod;
            tot++;
        }
        for(int j = 0; j < tot && i * prime[j] < N; j++){
            prime_tag[i * prime[j]] = true;
            if(i % prime[j] == 0){
                f[i * prime[j]] = (ll)f[i] * g[j] % mod;
                break;
            }else
                f[i * prime[j]] = (ll)f[i] * f[prime[j]] % mod;
        }
    }
    f[0] = 0;
    for(int i = 1; i < N; i++)
        f[i] = (f[i] + f[i-1]) % mod;

}
ll solve(){
    ll res = 0;
    for(int l = 1,r ; l <= n; l = r + 1){
        r = min(n / (n / l), m / (m / l));
        res += (f[r] - f[l - 1] + mod ) % mod  * (n / l) % mod * (m / l) % mod ;
       //printf("f[r] - f[l - 1] = %lld ,res = %lld\n",f[r] - f[l - 1],res);
    }
    return res % mod;
}
int main(){
    scanf("%d %d", &t, &k);
    init();
    while(t--) {
        scanf("%d %d", &n, &m);
        if(n > m) swap(n, m);
        printf("%lld\n", solve());
    }
    return 0;
}

【例4】P1829 [國家集訓隊]Crash的數字表格 / JZPTAB
題意

爲了研究最小公倍數,CrashCrash畫了一張NMN*M的表格,每個格子裏寫了一個數字,其中第ii行第jj列的那個格子裏寫着數LCM(i,j)LCM(i,j)CrashCrash想知道表格裏所有的數的和mod 20101009的值。

思路
首先將問題轉化爲數學形式,保證N<=MN<=M,如果大就進行交換:

ans=i=1Nj=1Mlcm(i,j)ans = \displaystyle\sum_{i =1}^{N}\sum_{j = 1}^{M}lcm(i,j)

=i=1Nj=1Mijgcd(i,j)= \displaystyle\sum_{i =1}^{N}\sum_{j = 1}^{M}\frac{i*j}{gcd(i,j)}

d=gcd(i,j)d = gcd(i,j),我們枚舉dd,則:
ans=dN1diNjMi×j[ gcd(i,j)==d ]ans = \displaystyle\sum_{d}^{N}\frac{1}{d}\sum_{i}^{N}\sum_{j}^{M}i\times j[\ gcd(i,j)==d\ ]

f(N,M,d)=iNjMi×j[ gcd(i,j)==d ]f(N,M,d) = \displaystyle\sum_{i}^{N}\sum_{j}^{M}i\times j[\ gcd(i,j)==d\ ]
g(N,M,d)=iNjMi×j[ d  gcd(i,j) ]=diNidjMj=d2×Nd(Nd+1)2×Md(Md+1)2g(N,M,d) = \displaystyle\sum_{i}^{N}\sum_{j}^{M}i\times j[\ d\ |\ gcd(i,j)\ ]=\sum_{d|i}^{N}i\sum_{d|j}^{M}j =d^2\times\frac{\lfloor\frac{N}{d}\rfloor(\lfloor\frac{N}{d}\rfloor+1)}{2}\times\frac{\lfloor\frac{M}{d}\rfloor(\lfloor\frac{M}{d}\rfloor+1)}{2}

這裏是一個循環對jj求和,一個循環對ii求和,iNjMi×j\displaystyle\sum_{i}^{N}\sum_{j}^{M}i\times ji1Ndj1Mdd2×i1×j1\displaystyle\sum_{i_1}^{\lfloor\frac{N}{d}\rfloor}\sum_{j_1}^{\lfloor\frac{M}{d}\rfloor}d^2\times i_1\times j_1等價

簡要證明:首先我們知道 i[1,N],j[1,M]i\in[1,N],j\in[1,M],滿足 gcd(i,j)==dgcd(i,j) == d 的數對個數是Nd×Md{\lfloor\frac{N}{d}\rfloor}\times{\lfloor\frac{M}{d}\rfloor},我們將 i,ji,j 除以 dd ,縮小了範圍,將i,ji,j的範圍從 [1,N] 和 [1,M] 縮小到了 [1,Nd{\lfloor\frac{N}{d}\rfloor}] 和[1,Md{\lfloor\frac{M}{d}\rfloor}],變成了i1,j1i_1,j_1i=d×i1,j=d×j1i= d\times i_1,j= d\times j_1

開始莫比烏斯反演:

f(d)=dnμ(nd)g(n)=dnμ(nd)×n2×Nn(Nn+1)2×Mn(Mn+1)2f(d) = \displaystyle\sum_{d | n}\mu(\frac{n}{d})g(n)=\sum_{d | n}\mu(\frac{n}{d})\times n^2\times\frac{\lfloor\frac{N}{n}\rfloor(\lfloor\frac{N}{n}\rfloor+1)}{2}\times\frac{\lfloor\frac{M}{n}\rfloor(\lfloor\frac{M}{n}\rfloor+1)}{2}

ans=d=1N1d×f(d)ans = \displaystyle\sum_{d=1}^{N}\frac{1}{d}\times f(d)
ans=d=1N1ddnμ(nd)×n2×Nn(Nn+1)2×Mn(Mn+1)2ans = \displaystyle\sum_{d =1}^{N}\frac{1}{d}\sum_{d|n}\mu(\frac{n}{d})\times n^2\times\frac{\lfloor\frac{N}{n}\rfloor(\lfloor\frac{N}{n}\rfloor+1)}{2}\times\frac{\lfloor\frac{M}{n}\rfloor(\lfloor\frac{M}{n}\rfloor+1)}{2}

x=ndx = \frac{n}{d},枚舉xx

ans=d=1N1dxNdμ(x)×d2×x2×Nn(Nn+1)2×Mn(Mn+1)2ans = \displaystyle\sum_{d=1}^{N}\frac{1}{d}\sum_{x}^{\lfloor\frac{N}{d}\rfloor}\mu(x)\times d^2\times x^2\times \frac{\lfloor\frac{N}{n}\rfloor(\lfloor\frac{N}{n}\rfloor+1)}{2}\times\frac{\lfloor\frac{M}{n}\rfloor(\lfloor\frac{M}{n}\rfloor+1)}{2}

ans=d=1NxNdμ(x)×x×n×Nn(Nn+1)2×Mn(Mn+1)2ans = \displaystyle\sum_{d=1}^{N}\sum_{x}^{\lfloor\frac{N}{d}\rfloor}\mu(x)\times x\times n\times \frac{\lfloor\frac{N}{n}\rfloor(\lfloor\frac{N}{n}\rfloor+1)}{2}\times\frac{\lfloor\frac{M}{n}\rfloor(\lfloor\frac{M}{n}\rfloor+1)}{2}

ans=n=1Nn×Nn(Nn+1)2×Mn(Mn+1)2xnμ(x)×xans = \displaystyle\sum_{n=1}^{N}n\times \frac{\lfloor\frac{N}{n}\rfloor(\lfloor\frac{N}{n}\rfloor+1)}{2}\times\frac{\lfloor\frac{M}{n}\rfloor(\lfloor\frac{M}{n}\rfloor+1)}{2}\sum_{x|n}\mu(x)\times x

前一部分直接可以數論整除分塊,根據莫比烏斯反演的性質後一部分是一個積性函數,我們在線性篩中預處理。

f1(n)=xnμ(x)×xf_1(n) =\displaystyle\sum_{x|n}\mu(x)\times x

根據唯一分解定理:

n=p1c1p2c2p3c3...pkckn = p_1^{c1} p_2^{c2} p_3^{c3}... p_k^{ck}

f1(n)=f1(p1c1p2c2p3c3...pkck)=i=1kpici\displaystyle f_1(n) = f_1(p_1^{c1} p_2^{c2} p_3^{c3}... p_k^{ck}) = \prod_{i=1}^{k}p_i^{ci}

對於f1(n)f_1(n),當 n  is  primen\ \ is\ \ prime 時,在求和的過程中,根據莫比烏斯函數的性質,只有當 xx 只有 n,1n,1 兩個值可取,的時候對和有貢獻。所以當 n  is  primen\ \ is\ \ prime 時,f1(n)=1nf_1(n)=1-n

這樣我們線性篩的時候就很簡單了:

i mod prime[j]==1i \ mod\ prime[j] == 1時,f1(iprime[j])=f1(i)×f1(prime[j])f_1(i*prime[j])=f_1(i)\times f_1(prime[j])

i mod prime[j]==0i \ mod\ prime[j] == 0時,f1(iprime[j])=f1(i)=1if_1(i*prime[j])=f_1(i)=1-i

p=prime[j]p = prime[j]
.
i mod p==0i \ mod\ p == 0時,np,n\frac{n}{p},n 都是 pp 的倍數,
.
f1(n)f1(np)=(1p1)(1p2)...(1pk)(1p1)(1p2)...(1pk)=1\displaystyle \frac{f_1(n)}{f_1(\frac{n}{p})}=\frac{(1-p_1)(1-p_2)...(1-p_k)}{(1-p_1)(1-p_2)...(1-p_k)}=1

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;

const int mod = 20101009;
const int Max = 1e7 + 10;
int prime[Max],prime_tot = 0,f[Max],s[Max];
bool prime_tag[Max] = {0};
int n,m;

void get_prime(){
	f[1] = 1;
	for(int i = 2; i < Max; i++){
		if(!prime_tag[i]){
			prime[prime_tot++] = i;
			f[i] = (1 - i + mod) % mod;
		}
		for(int j = 0 ; j < prime_tot && i * prime[j] < Max; j++){
			prime_tag[i * prime[j]]  = true;
			if(i % prime[j] == 0){
				f[i * prime[j]] = f[i];
				break;
			}else{
				f[i * prime[j]] = 1ll * f[i] * f[prime[j]] % mod ;
			}
		}
	}
	f[0] = 0;
	for(int i = 1; i < Max; i++)
		f[i] = (f[i-1]  + 1ll * f[i] * i % mod) % mod;
}
ll solve(){
	ll ans = 0,t1,t2,t3;
	for(int l = 1,r; l <= n; l = r + 1){
		r = min(n / (n / l),m / (m / l));
		t1 = 1ll *(f[r] - f[l-1] + mod ) % mod;
		t2 = 1ll * (n / l) * (n / l + 1) / 2 % mod;
		t3 = 1ll * (m / l) * (m / l + 1)  / 2 % mod;
		ans += t1 % mod * t2 % mod * t3 % mod ;
	}
	return ans % mod;
}
int main(){
	get_prime();
	scanf("%d%d",&n,&m);
	if(n > m) swap(n,m);
	printf("%lld",solve());
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章