狄利克雷卷積&莫比烏斯反演總結


狄利克雷卷積&莫比烏斯反演總結

Prepare

1、\([P]\)表示當\(P\)為真時\([P]\)\(1\),否則為\(0\)

2、\(a|b\)\(b\)\(a\)整除。

3、一些奇怪常見的函數:

\(1(n)=1\)

\(id(n)=n\)

\(\sigma(n)=n的約數和\)

\(d(n)=n的約數個數\)

\(\epsilon(n)=[n==1]\)

狄利克雷卷積

數論函數

數論函數指一類定義域是正整數,值域是一個數集的函數。

加法:逐項相加就可以辣\((f+g)(x)=f(x)+g(x)\)

數乘:用一個常數乘\((xf)(n)=x*f(n)\)

狄利克雷卷積

定義兩個數論函數的狄利克雷卷積\(*\)

\(t=f*g\)

\[t(n)=\sum_{i|n}f(i)g(\frac{n}{i}) \]

等價於

\[t(n)=\sum_{ij=n}f(i)g(j) \]

狄利克雷卷積有以下性質(兩個數論函數相等,是指兩個函數的每一項都相等):

1、交換律\(f*g=g*f\)

2、結合律\(f*(g*h)=(f*g)*h\)

3、分配律\(f*h+g*h=(f+g)*h\)

4、沒有名字\((xf)*g=x(f*g)\)

5、單位元\(\epsilon*f=f\),其中\(\epsilon(n)=[n==1]\)

6、逆元:對於每一個\(f(1)\neq 0\)的函數\(f\),都有\(f*g=\epsilon\)

討論一下第六個結論,如何求一個函數的逆呢?

只需要定義

\[g(n)=\frac{1}{f(1)}\left([n==1]-\sum_{i|n,i\neq 1}f(i)g(\frac{n}{i})\right) \]

這樣的話

\[\sum_{i|n}f(i)g(\frac{n}{i})=f(1)g(n)+\sum_{i|n,i\neq1}f(i)g(\frac{n}{i})=[n==1] \]

積性函數

如果一個數論函數\(f\)有當\(gcd(n,m)==1\)

\[f(nm)=f(n)f(m) \]

就稱\(f\)為積性函數。

一些常見的積性函數:

\(\epsilon(n)=[n==1]\),\(id(n)=n\),\(id^{k}(n)=n^k\)

事實上他們也滿足完全積性(即當\(gcd(n,m)\neq1\)時,也有\(f(nm)=f(n)f(m)\))

特殊的,我們令\(id^0(n)=1(n)=1\)

還有兩個普通的積性函數

\(d(n)=n的約數和\)\(\varphi(n)=[1,n]中與n互質的數的個數\)

還有兩個重要結論:

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

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

積性函數有什么用呢?

它可以線性篩

然而還有更有用的\(---\)

莫比烏斯反演

一些理論

我們定義\(1\)的逆是\(\mu\)

這樣的話,如果\(g=f*1\),就有\(f=f*1*\mu=g*\mu\)

換句話說,就是

\[g(n)=\sum_{d|n}f(d)\Leftrightarrow f(n)=\sum_{d|n}\mu(\frac{n}{d})g(d) \]

也可以這樣子

\[g(d)=\sum_{d|n}f(n)\Leftrightarrow f(d)=\sum_{d|n}\mu(\frac{n}{d})*g(n) \]

例子

怎么用呢?舉幾個例子(以下情況默認\(n\leq m\))


\(Eg1\)

\[\sum_{i=1}^n\sum_{i=1}^m[gcd(i,j)==1] \]

然后怎么辦呢?

\[f(x)=\sum_{i=1}^n\sum_{i=1}^m[gcd(i,j)==x] \\ g(x)=\sum_{x|d}f(d) \]

\[f(1)=\sum_{1|d}\mu(\frac{d}{1})g(d) \\ f(1)=\sum_{i=1}^n\mu(i)g(i) \]

考慮\(g(x)\)是什么

\[g(x)=\sum_{x|d}\sum_{i=1}^n\sum_{i=1}^m[gcd(i,j)==d] \]

\[g(x)=\sum_{i=1}^n\sum_{i=1}^m[x|gcd(i,j)] \\ g(x)=\sum_{i=1}^{\left\lfloor\frac nx\right\rfloor}\sum_{i=1}^{\left\lfloor\frac mx\right\rfloor}[1|gcd(i,j)]\\ g(x)=\left\lfloor\frac nx\right\rfloor\left\lfloor\frac mx\right\rfloor \]

帶回\(f(1)\)

\[Ans=\sum_{x=1}^n\mu(x)\left\lfloor\frac nx\right\rfloor\left\lfloor\frac mx\right\rfloor \]

這個用整除分塊可以做到\(O(\sqrt n)\)


\(Eg2\)

\[\sum_{i=1}^n\sum_{j=1}^mgcd(i,j) \]

可化為

\[\sum_{d=1}^n\sum_{i=1}^n\sum_{j=1}^md[gcd(i,j)==d] \\ \sum_{d=1}^nd\sum_{i=1}^{\left\lfloor\frac nd\right\rfloor}\sum_{j=1}^{\left\lfloor\frac md\right\rfloor}[gcd(i,j)==1] \]

\[x=\left\lfloor\frac nd\right\rfloor, y=\left\lfloor\frac md\right\rfloor \]

\[\sum_{d=1}^nd\sum_{i=1}^x\sum_{j=1}^y[gcd(i,j)==1] \]

套入我們剛才在\(Eg1\)求得的

\[\sum_{d=1}^nd\sum_{i=1}^x\mu(i)\left\lfloor\frac xi\right\rfloor\left\lfloor\frac yi\right\rfloor\\ \sum_{d=1}^nd\sum_{i=1}^{n/d}\mu(i)\left\lfloor\frac {x}{id}\right\rfloor\left\lfloor\frac {y}{id}\right\rfloor \]

化到現在是\(O(n)\)的,因為前后都可以數論分塊

但是我們能做得更好

\(T=id\)

原式化為

\[\sum_{d=1}^nd\sum_{i=1}^n\mu(i)\left\lfloor\frac {x}{T}\right\rfloor\left\lfloor\frac {y}{T}\right\rfloor\\ \sum_{T=1}^n\left\lfloor\frac {x}{T}\right\rfloor\left\lfloor\frac {y}{T}\right\rfloor\sum_{d|T}d\mu(\frac Td) \]

乍一看還是\(O(n)\)的呀,但是對於后面那一坨

\[f(T)=\sum_{d|T}d\mu(\frac Td)\\ \Leftrightarrow\\ f(T)=\sum_{ij=T}id(i)\mu(j) \]

兩個積性函數相乘,可以線性篩呀!!

所以復雜度被我們壓到了\(O(\sqrt n)\)

\(upd\;on\;2019.3.9:\)

發現以前沒有講線性篩,導致現在自己都不知道是怎么搞得了。。。

線性篩

我們篩\(\mu\)的函數是長這樣的(自動認為有模數):

int prime[MAX_N], mu[MAX_N]
bool nprime[MAX_N]; 
void sieve() { 
	mu[1] = 1;
	for (int i = 2; i <= N; i++) {
		if (!nprime[i]) prime[++tot] = i, mu[i] = Mod - 1; 
		for (int j = 1; i * prime[j] <= N; j++) { 
			nprime[i * prime[j]] = 1; 
			if (i % prime[j] == 0) break; 
			mu[i * prime[j]] = Mod - mu[i]; 
		} 
	} 
} 

其實就是和篩素數的是一樣的,

if (i % prime[j] == 0) break;

這句話保證了復雜度,因為你存的素數是遞增的,

如果\(i\)\(prime[j]\)整除后,\(i*prime[j+k](k>0)\)一定可以被\(prime[j]*x\)的形式表示出來。

那么就有我們下面的一個問題:


\(Eg3\)

給定你一個數組\(f\),求

\[\sum_{i=1}^n\sum_{j=1}^mf[gcd(i,j)] \]

其中\(n,m\leq 10^7\),數據組數\(T\leq 10^4\)

由我們上面推的東西,將\(f\)看作一個數論函數,可以知道只要求出一個函數\(g=\mu * f\)的前綴和,

這個問題就解決了。

一下是解決這個問題的幾種方法(蒯的):

void get_g_1(int N, const int *f, int *g) {
  for (int i = 1; i <= N; i++) g[i] = 0;
  for (int i = 1; i <= N; i++)
    for (int j = 1; i * j <= N; j++)
      g[i * j] = (g[i * j] + mu[i] * f[j]) % mod;
} // 依照定義,O(nlogn)

void get_g_2(int N, const int *f, int *g) {
  for (int i = 1; i <= N; i++) g[i] = f[i];
  for (int i = 1; i <= N; i++)
    for (int j = 2; i * j <= N; j++)
      g[i * j] = (g[i * j] - g[i]) % mod;
} // 類似求狄利克雷卷積逆的方式,不需要線性篩 mu ,O(nlogn)

void get_g_3(int N, const int *f, int *g) {
  for (int i = 1; i <= N; i++) g[i] = f[i];
  for (int i = 0; i < prime_count; i++)
    for (int j = N / prime[i]; j >= 1; j--)
      g[j * prime[i]] = (g[j * prime[i]] - g[j]) % mod;
} // Magic! O(nloglogn)

對於最后一種方法,理解成dp:

\[g_{i,n}=\sum_{d|n,d只包含前i種質因子}\mu(d)f(n/d) \]

那么轉移:

\[g_{i,n}=\begin{cases} g_{i-1,n}\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;p_i\nmid n\\ g_{i-1,n}-g_{i-1,n/p_i}\;\;\;\;\;p_i\mid n \end{cases} \]

復雜度\(O(n\log\log n)\)


參考文章1

參考文章2


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM