天天看點

Dirichlet 字首和及其應用

\[\Huge\text{Dirichlet 字首和及其應用}

\]

全文概要

  1. Dirichlet 字首和定義;
  2. Dirichlet 字首和的算法,及其拓展;
  3. Mobius 函數,Mobius 反演以及它們與 Dirichlet 字首和,Dirichlet 卷積之間關系;
  4. 具體應用。

1 Dirichlet 字首和定義

給定數列 \(a_i\),定義數列 \(b_i=\sum\limits_{d|i} a_d\),即所有下标為該下标約數的原數組之和。

例子:\(n=10,a_i=\left\{1,4,6,9,2,4,5,6,4,3\right\}\),則 \(b_i=\left\{1,5,7,14,3,15,6,20,11,10\right\}\)

2 模闆問題與複雜度

2.1 Dirichlet 字首和

模闆

2.1.1 算法說明

\(n\le 2\times 10^7\),說明要用優于/微劣于 \(\mathcal{O}(n)\) 的算法。

對于一個數 \(a_j\),它會被計算到 \(b_{1\times j},b_{2\times j}\dots\) 中。

而對于 \(a_k(k\ge 1,k|j)\) ,可以發現會被記入 \(b_{1\times k},b_{2\times k},b_{3\times k}\dots\)

可見 \(b_{1\times j},b_{2\times j}\dots\) 也肯定會被包含;

是以可以得到一個結論:\(b_j\) 會被 \(b_{1\times j},b_{2\times j},b_{3\times j}\dots\) 所包含。

但是如果直接計算 \(b_{4\times j}\),會被 \(b_{j}\) 和 \(b_{2\times j}\) 同時計入,有重複;

于是稍稍變換計算方式:每次乘以一個不超過其下标本身的質數,就可以解決這個問題,也能夠保證不重複地計算。

核心代碼:

for(int i=1;i<=cnt;i++)
		for(int j=1;j*pr[i]<=n;j++) a[j*pr[i]]+=a[j];
           

其中

cnt

是所有素數的總數,

pr[i]

為第 \(i\) 個素數。

2.1.2 算法正确性證明

下面證明上述代碼是正确的,也即不重複且不遺漏:

下證第 \(i(i\le cnt)\) 輪過後,對于滿足 \(l|d,\frac{d}{l}=pr_1^{\alpha_1}pr_2^{\alpha_2}\dots pr_i^{\alpha_i}\) 的 \(l\),令這些 \(l\) 組成集合 \(S_{i,d}\)。\(b_d=\sum\limits_{l\in S_{i,d}} a_l\)

\(i=0\) 時,顯然成立!(\(b_i=a_i\))

假設對 \(i=k-1\) 成立,此時 \(b_1=a_1\),\(j=1\) 成立!

假設 \(b_1\dots b_p\) 均滿足如上結論,

\(p=j+1\) 時,如果 \(pr_i|j+1\),那麼 \(b_{j+1}\leftarrow b_{j+1}+b_{\frac{j+1}{pr_i}}\),即 \(b_{j+1}=\sum\limits_{l\in{S_{k-1,j+1}}}a_l+\sum\limits_{l\in{S_{k,\frac{j+1}{pr_i}}}}a_l\)

由定義可知 \(S_{k,\frac{j+1}{pr_i}}\cap S_{k-1,j+1}=\varnothing\),且 \(S_{k,\frac{j+1}{pr_i}}\cup S_{k-1,j+1}=S_{k,j+1}\);

是以 \(b_{j+1}=\sum\limits_{l\in{S_{k,j+1}}}a_l\)

得證!

2.1.3 舉例驗證

舉個例子直覺地驗證一下各個數字的變化情況:\(n=10,cnt=4,pr_i=\left\{2,3,5,7\right\}\)

初始情況:

a1,a2,a3,a4,a5,a6,a7,a8,a9,a10

\(i=1,pr_i=2\) 後:

a1,a2+a1,a3,a4+a2+a1,a5,a6+a3,a7,a8+a4+a2+a1,a9,a10+a5

\(i=2,pr_i=3\) 後:

a1,a2+a1,a3+a1,a4+a2+a1,a5,a6+a3+a2+a1,a7,a8+a4+a2+a1,a9+a3+a1,a10+a5

\(i=3,pr_i=5\) 後:

a1,a2+a1,a3+a1,a4+a2+a1,a5+a1,a6+a3+a2+a1,a7,a8+a4+a2+a1,a9+a3+a1,a10+a5+a2+a1

\(i=4,pr_i=7\) 後:

a1,a2+a1,a3+a1,a4+a2+a1,a5+a1,a6+a3+a2+a1,a7+a1,a8+a4+a2+a1,a9+a3+a1,a10+a5+a2+a1

2.2 Dirichlet 字尾和

類似的,給定數列 \(a_i\),定義數列 \(b_i=\sum\limits_{i|d} a_d\)。

即所有下标為該下标倍數的原數組之和。

我們可以如下操作:每次同樣乘以一個不超過其下标本身的質數,但是由于字首變為字尾,是以把計算順序改變一下——變成從後向前計算。

為什麼呢?畫張圖。

Dirichlet 字首和及其應用

上圖為 Dirichlet 字首和,下面的數字代表給他貢獻的 \(a\) 數組下标,上面是 \(b\) 數組下标

Dirichlet 字首和及其應用

上圖為 Dirichlet 字尾和

for(int i=1;i<=cnt;i++)
	for(int j=n/pr[i];j>=1;j--) a[j]+=a[j*pr[i]];
           

用類似 Dirichlet 字首和的證法也可以得證!

2.3 逆推 Dirichlet 字首和

即已知字首和 \(b_i\),求原數組 \(a_i\);

相當于是一個差分(Dirichlet 差分)。

是以直接按照字首和的代碼倒序周遊即可。

for(int i=cnt;i>=1;i--)
		for(int j=n/pr[i];j>=1;j--) a[j*pr[i]]-=a[j];
           

2.4 逆推 Dirichlet 字尾和

還是 Dirichlet 差分,可以按照字尾和代碼倒序周遊。

for(int i=cnt;i>=1;i--)
		for(int j=1;j*pr[i]<=n;j++) a[j]-=a[j*pr[i]];
           

2.5 Dirichlet 字首和及其拓展複雜度

這個算法複雜度為 \(\mathcal{O}(\sum\limits_{\text{質數p}\le n} \dfrac{n}{p})\),與埃氏篩的複雜度相同,是以可以得知複雜度約為 \(\mathcal{O}(n\log\log n)\)

3 Dirichlet 卷積 和 Mobius 反演

3.1 Dirichlet 卷積 和 Mobius 函數之間的關系

3.1.1 什麼是Dirichlet 卷積

Dirichlet 卷積,是定義在兩個數論函數 \(f,g\) 上的 \(f*g\) 滿足 \((f*g)(n)=\sum\limits_{d|n}f(d)\times g(n/d)\)

Dirichlet 卷積滿足如下的規律:

  • 交換律:\(f*g=g*f\)
  • 結合律:\((f*g)*h=f*(g*h)\)
  • 配置設定律:\(f*(g+h)=f*g+f*h\)
  • 存在機關元:定義 \(\epsilon(n)=[n=1]\),則 \(f*\epsilon =f\)
  • 保持積性:如果 \(f,g\) 都是積性函數,那麼 \(f*g\) 也是積性函數。

3.1.2 什麼是 Mobius 函數

Mobius 函數用 \(\mu\) 來表示。

如果 \(n=1\) 則 \(\mu(n)=1\);

如果 \(n\) 沒有平方因子,則 \(\mu(n)=(-1)^{\text{n的素因子個數}}\);

如果 \(n\) 有平方因子,則 \(\mu(n)=0\)。

定理一:

\[\epsilon(n)=\sum\limits_{d|n}\mu(d)

即 \(\epsilon=\mu*1\);

證明:

設 \(n=p_1^{\alpha_1}p_2^{\alpha_2}\dots p_k^{\alpha_k},n'=\prod\limits_{i=1}^{k} p_i\)

是以 \(\sum\limits_{d|n} \mu(d)=\sum\limits_{d|n'}\mu(d)=\sum\limits_{i=0}^{k}C^i_k\times (-1)^k=(1+(-1))^k=[n=1]=\epsilon(n)\)

是以我們可以利用 Dirichlet 卷積處理 Mobius 函數!

3.1.3 莫比烏斯反演

如果函數 \(f,g\) 滿足

\[f(n)=\sum\limits_{d|n} g(d)

\[g(n)=\sum\limits_{d|n}\mu(d)f(\dfrac{n}{d})

證明:根據定義可以得到 \(f=g*1\)

兩邊同時卷上 \(\mu\)

可以得到:

\[f*\mu=g*1*\mu

\[\because 1*\mu =\epsilon

\[\therefore f* \mu=g*\epsilon=g

因為 \(\mu(p^k)=[k=1]\),而且 \(\mu\) 是積性函數,是以可以用線性篩模闆計算。

void prime(ll n){
	mu[1]=1;
	for(int i=2;i<=n;i++){
		if(!vst[i]) pr[++cnt]=i,mu[i]=-1;
		for(ll j=1;j<=cnt&&i*pr[j]<=n;j++){
			vst[i*pr[j]]=1;
			if(!(i%pr[j])){mu[i*pr[j]]=0;break;}
			mu[i*pr[j]]=-mu[i];
		}
	}
}
                                 
           

3.2 複雜度的分析

假設我們現在要算 \(f=g*1\),如果對于每一個 \(f_i\) 都是暴力計算,複雜度是 \(\mathcal{O}(\sqrt n)\) 的,總和是 \(\mathcal{O}(n\sqrt n)\);

如果預計算完了每個數的約數清單,可以得知複雜度約為 \(\mathcal{O}(n/1+n/2+\dots n/n)\),而每個數計算也需要其約數個數的複雜度。

而 \(\lim\limits_{n\rightarrow \infty}\sum\limits_{i=1}^{n}\dfrac{n}{i}=n\ln n\)(素數定理)

是以預計算約數的複雜度總和是 \(\mathcal{O}(n\log n)\)。

而我們使用了 Dirichlet 卷積以後複雜度下降為 \(\mathcal{O}(n\log \log n)\)。

主要的差距就在于 Dirichlet 卷積以後我們省去了重新計算 \(f_d(d|i)\) 的過程。

舉個例子:在前兩種情況,計算 \(f_{10}\) 時,前兩種方法都會将 \(f_5\) 重新計算,但是事實上在 Dirichlet 卷積當中 之前計算好的 \(f_5\) 可以被重複利用,進而減少計算次數。

3.3 從多元空間看 Dirichlet 字首和

我們回過頭來看一看 \(n=10\) 時最後的 \(b_i\):

a1,a2+a1,a3+a1,a4+a2+a1,a5+a1,a6+a3+a2+a1,a7+a1,a8+a4+a2+a1,a9+a3+a1,a10+a5+a2+a1

乍看之下似乎沒有規律。

如果我們将 \(i\) 質因數分解以後,并且以各個質因數的幂次作為坐标呢?

Dirichlet 字首和及其應用

舉個比較形象的例子:(為了表示友善暫時隻列出前三根軸)紅色線條框出的立方體即為 \(b_{30}\) 所包含的所有 \(a_d\) 在這個空間中的坐标,而藍色框出的部分即為 \(b_{100}\) 所包含的 \(a_d\)。

如果我們要在這個空間内做差分的話,由容斥原理,令 \(n=p_1^{\alpha_1}p_2^{\alpha_2}\dots p_k^{\alpha_k}\) 可得

\[a_{n}=\sum\limits_{d|n,\frac{n}{d}=p_1^{\beta_1}p_2^{\beta_2}\dots p_k^{\beta_k},\beta_i\in{0,1}} (-1)^{\sum\limits_{i=1}^{n} \beta_i}\times b_d

\[\therefore a_{n}=\sum\limits_{d|n,\frac{n}{d}=p_1^{\beta_1}p_2^{\beta_2}\dots p_k^{\beta_k},\beta_i\in{0,1}} \mu\left(\dfrac{n}{d}\right)\times b_d

由 Mobius 函數的定義,如果存在平方的質數為 \(n\) 約數,\(\mu(n)=0\)。

\[\therefore a_{n}=\sum\limits_{d|n} \mu\left(\dfrac{n}{d}\right)\times b_d

\[\therefore a_{n}=\sum\limits_{d|n} \mu\left(d\right)\times b_{\frac{n}{d}}

這就是 Dirichlet 差分!

再看一下 Mobius 反演的式子:

會發現 Dirichlet 差分和 Mobius 反演本質一樣。

借此發現了 Dirichlet 字首和/差分 與 Mobius 反演之間的關系。

4 具體的應用

例題1

即求

\[\sum\limits^{n}_{x=1}\sum\limits^{m}_{y=1}[\gcd(x,y)\text{為質數}]

設 \(g(x)\) 為 \(\gcd(i,j)=x\) 的個數,\(f(x)\) 為 \(\gcd(i,j)=k\times d,k=1,2,\dots\) 的個數。(假設是單組資料)

\[\therefore g(x)=\sum\limits^{n}_{i=1}\sum\limits^{m}_{j=1}[\gcd(i,j)=d],f(x)=\sum\limits^{n}_{i=1}\sum\limits^{m}_{j=1}[\gcd(i,j)=kd]

\[f(x)=\sum\limits_{d|x} g(d)=\left\lfloor\dfrac{n}{x}\right\rfloor\left\lfloor\dfrac{m}{x}\right\rfloor

\[g(x)=\sum\limits_{x|d}\mu\left(\left\lfloor\dfrac{d}{x}\right\rfloor\right)f(x)

\[\sum\limits_{\text{p是質數}}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m} [\gcd(i,j)=p]

把 \(g(p)\) 的表達式代入。

\[\sum\limits_{\text{p是質數}}g(p)

可以使用莫比烏斯反演!

\[\sum_{\text{p是質數}}\sum\limits_{p|d}\mu\left(\left\lfloor\dfrac{d}{p}\right\rfloor\right)f(d)

改變枚舉項,枚舉

\[\left\lfloor\dfrac{d}{p}\right\rfloor

\[\sum\limits_{\text{p是質數}}\sum\limits_{d=1}^{\min(\frac{n}{p},\frac{m}{p})}\mu(d)f(d\times p)=\sum\limits_{\text{p是質數}}\sum\limits_{d=1}^{\min(\frac{n}{p},\frac{m}{p})}\mu(d)\left\lfloor\dfrac{n}{d\times p}\right\rfloor\left\lfloor\dfrac{m}{d\times p}\right\rfloor

把 \(

d\times p\) 換元成

\(T\) 可以得到:

\[\sum\limits_{T=1}^{\min(n,m)}\sum\limits_\text{p|T,p是質數}\mu\left(\left\lfloor\dfrac{T}{p}\right\rfloor\right)\left\lfloor\dfrac{n}{T}\right\rfloor\left\lfloor\dfrac{m}{T}\right\rfloor

再交換一下 \(\sum\) 的順序:

\[\sum\limits_{T=1}^{\min(n,m)}\left\lfloor\dfrac{n}{T}\right\rfloor\left\lfloor\dfrac{m}{T}\right\rfloor\sum\limits_\text{p|T,p是質數}\mu\left(\left\lfloor\dfrac{T}{p}\right\rfloor\right)

是以就可以線性篩 \(\mu\) 函數,整除分塊并記錄字首和。

複雜度 \(\mathcal{O}(n+\sqrt{n})\)。

4.後記