莫比烏斯反演
前置芝士:數論分塊
求 \(\sum\limits_{i=1}^n\lfloor\frac{n}{i}\rfloor\),其中 \(n\le10^{12}\)。
可以發現,\(\lfloor\frac{n}{i}\rfloor\) 最多隻有 \(\sqrt{n}\) 種取值,所以只需要列舉每種取值對應 \(i\) 的取值範圍即可。
ll ans = 0;
for(int i = 1,j;i <= n;i = j+1)
{
j = n/(n/i);
ans += (n/i)*(j-i+1);
}
積性函式:
如果函式 \(f\) 滿足 \(\forall a,b,\gcd(a,b)=1,f(ab)=f(a)f(b)\),則 \(f\) 為積性函式。
- 尤拉函式:\(\varphi(n)\),即 \(1\) 到 \(n\) 中與 \(n\) 互質的個數。
- 莫比烏斯函式:\(\mu(i)=\begin{cases}1&n=1\\(-1)^k&n=p_1p_2\ldots p_k\\ 0&otherwise\end{cases}\)
- 因子函式:\(d(n)\),即 \(n\) 的因子個數。
- 除數函式:\(\sigma(n)=\sum\limits_{d\mid n}d\),即 \(x\) 的因子之和。
完全積性函式:
如果函式 \(f(n)\) 滿足 \(\forall a,b,f(ab)=f(a)f(b)\),則 \(f(n)\) 為完全積性函式。
- 常數函式:\(I(n)=1\)
- 恆等函式:\(Id(n)=n\)
- 單位函式:\(\varepsilon(n)=[n=1]\)
狄利克雷卷積:
\((f\ast g)(n)=\sum\limits_{d\mid n}f(d)g(\frac{n}{d})\)
性質:
-
交換律:\(f\ast g=g\ast f\)
-
結合律:\((f\ast g)\ast h=f\ast(g\ast h)\)
-
分配律:\((f+g)\ast h=f\ast h+f\ast h\)
-
如果 \(f,g\) 是積性函式,則 \(f*g\) 也是積性函式。比如:
- \(Id\ast I=\sigma\)
- \(I\ast I=d\)
- \(\varphi\ast I=Id\)
- \(\mu\ast I=\varepsilon\)
下面是根據上面推出來的:
-
\(\varepsilon\ast f=f\),即 \(\varepsilon\) 與任何函式進行狄利克雷卷積後都是函式本身;
-
\(\varphi\ast d=\varphi\ast I\ast I=Id\ast I=\sigma\)
-
\(\because\varepsilon\ast Id=Id \therefore\mu\ast I\ast Id=\varphi\ast I \therefore\mu\ast Id=\varphi\)
-
\(\mu\ast \sigma=\mu\ast Id\ast I=\varepsilon\ast Id=Id\)
莫比烏斯反演:\([n=1]=\sum\limits_{d\mid n}\mu(d)\)
其實莫比烏斯反演還有一種形式:\(g(n)=\sum\limits_{d\mid n}f(d)\leftrightarrow f(n)=\sum\limits_{d\mid n}\mu(d)d(\frac{n}{d})\),也可以寫成:\(f\ast I=g\leftrightarrow f=g\ast\mu\)。
證明:\(\mu\ast I=\varepsilon\)
當 \(n=1\) 時顯然成立,當 \(n>1\) 時,設 \(n=p_1^{c_1}p_2^{c_2}\ldots p_k^{c_k}\),由於有平方因子的數的 \(\mu\) 為 \(0\),所以只需要證 \(n=p_1p_2\ldots p_k\) 時 \(\sum\limits_{d\mid n}\mu(\frac{n}{d})=0\)成立即可。
尤拉反演:\(n=\sum\limits_{d\mid n}\varphi(d)\)
證明:\(\varphi\ast I=Id\)
設 \(n=p_1^{c_1}p_2^{c_2}\ldots p_k^{c_k}\),因為 \(\varphi\) 是積性函式,則只需要證 \(n'=p^c\) 時成立即可。
線性篩 \(\varphi\) 和 \(\mu\)
線性篩分有重複因子和沒重複因子兩種情況,直接分情況討論即可。
int p[N],phi[N],mu[N],cnt;
bool isp[N];
ll sphi[N],smu[N];
void init()
{
phi[1] = mu[1] = 1;
for(int i = 2;i < N;i++)
{
if(!isp[i]){p[++cnt] = i;phi[i] = i-1;mu[i] = -1;}
for(int j = 1;j <= cnt&&p[j]*i < N;j++)
{
int now = i*p[j];
vis[now] = 1;
if(i%p[j]==0)
{
phi[now] = phi[i]*p[j];mu[now] = 0;
break;
}
phi[now] = phi[i]*(p[j]-1);mu[now] = -mu[i];
}
}
for(int i = 1;i < N;i++)
sphi[i] = sphi[i-1]+phi[i],smu[i] = smu[i-1]+mu[i];
}
例題
-
最基本的應用
求 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^m[\gcd(i,j)=1]\) 和 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^m\gcd(i,j)\),\(T\) 組資料,\(n,m\le 2\times10^6,T\le 1000\)
題太多了,甚至有十倍經驗。
直接莫比烏斯反演(以下預設 \(n\le m\)):
發現式子中只有 \(\lfloor\frac{n}{d}\rfloor\) 和 \(\lfloor\frac{m}{d}\rfloor\),直接數論分塊即可,時間複雜度 \(\mathcal{O}(n+T\sqrt{n})\)。
ll ans1 = 0,ans2 = 0;
for(int i = 1,j;i <= n;i = j+1)
{
j = min(n/(n/i),m/(m/i));
ans1 += (smu[j]-sum[i-1])*(n/i)*(m/i);
ans2 += (sphi[j]-sphi[i-1])*(n/i)*(m/i);
}
總結:莫比烏斯反演最重要的就是處理和式,經常推不出式子了就嘗試一下交換和式
- P2257 YY的GCD
求 \(\sum\limits_{i=1}^n \sum\limits_{j=1}^m[\gcd(i,j)\in prime]\), \(T\) 組資料,\(n,m\le 10^7,T\le 10^4\)。
考慮列舉 \(\gcd(i,j)\):
列舉 \(T=px\):
令 \(f(n)=\sum\limits_{p\mid n,p\in prime}\mu(\lfloor\frac{n}{p}\rfloor)\),只需要預處理出 \(f(n)\) 的字首和即可。具體的,列舉每一個質數,然後用類似埃式篩的方法求出 \(f(n)\)。時間複雜度 \(\mathcal{O}(n\log\log n+T\sqrt n)\)。
//預處理
for(int i = 1;i <= cnt;i++)
for(int j = p[i];j < N;j += p[i])
f[j] += mu[j/p[i]];
for(int i = 1;i < N;i++)f[i] += f[i-1];
//計算
for(int i = 1,j;i <= min(n,m);i = j+1)
{
j = min(n/(n/i),m/(m/i));
ans += (f[j]-f[i-1])*(n/i)*(m/i);
}
-
[P3327 SDOI2015] 約數個數和
設 \(d(n)\) 為 \(n\) 的約數個數,求 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^md(ij)\),\(T\) 組資料,\(T,n,m\le 5000\)。
考慮轉化 \(d(ij)\),將 \(ij\) 的因子與 \(i\) 和 \(j\) 的因子一一對應。如果 \(ij\) 的因子 \(k\) 中有一個因子 \(p^c\),\(i\) 中有 \(p^a\),\(j\) 中有 \(p^b\),則 \(c\le a+b\)。 那麼:
- 如果 \(c\le a\),那麼在 \(i\) 中選擇 \(p^a\);
- 如果 \(c>a\),那麼在 \(j\) 中選擇 \(p^{c-a}\)。
所以如果在 \(i\) 中選擇一個因子 \(x\),在 \(j\) 中選擇一個因子 \(y\) 且 \(\gcd(x,y)=1\),則 \(x,y\) 一定對應一個 \(ij\) 的因子。所以 \(d(ij)=\sum\limits_{x\mid i}\sum\limits_{y\mid j}[\gcd(x,y)=1]\)
發現括號裡面的東西可以預處理,令 \(f(n)=\sum\limits_{i=1}^n\lfloor\frac{n}{i}\rfloor\),則原式等於 \(\sum\limits_{d=1}^n\mu(i)f(\lfloor\frac{n}{d}\rfloor)f(\lfloor\frac{m}{d}\rfloor)\),數論分塊即可。時間複雜度 \(\mathcal{O}(n\sqrt{n}+T\sqrt{n})\)。
//預處理
for(int i = 1;i < N;i++)
for(int j = 1,k;j <= i;j = k+1)
{
k = i/(i/j);
f[i] += (k-j+1)*(i/j);
}
//計算
for(int i = 1,j;i <= min(n,m);i = j+1)
{
j = min(n/(n/i),m/(m/i));
ans += (smu[j]-smu[i-1])*f[n/i]*f[m/i];
}
-
P1829 Crash的數字表格
求:\(\sum\limits_{i=1}^n\sum\limits_{j=1}^m\operatorname{lcm}(i,j)\),\(T\) 組資料,\(n,m\le 10^7,T\le 10^4\)
因為 \(\operatorname{lcm}(i,j)=\frac{ij}{\gcd(i,j)}=\gcd(i,j)\times\frac{i}{\gcd(i,j)}\times\frac{j}{\gcd(i,j)}\),列舉 \(\gcd(i,j)\):
為了單獨計算後半邊式子,記 :
另外,記 \(S(n)=\sum\limits_{i=1}^ni=\frac{n(n+1)}{2}\),那麼:
其實到這裡就可以數論分塊套數論分塊做了,時間複雜度 \(\mathcal{O}(Tn^{\frac{3}{4}})\),但事實上原式還可以最佳化。
把 \(d\) 乘進去:
先列舉 \(T=dk\):
發現後半部分其實是可以預處理的,只需要求出 \(T\sum\limits_{k\mid T}\mu(k)k\) 的字首和即可。令函式 \(f(n)=\sum\limits_{k\mid n}\mu(k)k\),不難證明 \(f\) 是積性函式,所以可以線上性篩的時候順便求。具體的,如果在用 \(i\) 篩 \(i\times p\) 時 \(x\) 有平方因子,即 \(p\mid i\),因為 \(\mu(n)\) 在 \(n\) 有平方因子時為 \(0\),所以 \(f(i\times p)=f(i)\);如果沒有平方銀子,根據積性函式的性質,有 \(f(i\times p)=f(i)\times f(p)\)。時間複雜度 \(\mathcal{O}(T\sqrt n)\)。
//預處理
void init()
{
f[1] = 1;
for(int i = 2;i < N;i++)
{
if(!vis[i])p[++cnt] = i,f[i] = mod+1-i;
for(int j = 1;j <= cnt&&i*p[j] < N;j++)
{
int now = i*p[j];vis[now] = 1;
if(i%p[j]==0){f[now] = f[i];break;}
f[now] = f[i]*f[p[j]]%mod;
}
}
for(int i = 1;i < N;i++)f[i] = (f[i-1]+f[i]*i)%mod;
}
//計算
for(int i = 1,j;i <= n;i = j+1)
{
j = min(n/(n/i),m/(m/i));
(ans += (f[j]-f[i-1]+mod)*S(n/i)%mod*S(m/i)) %= mod;
}
-
[P3312 SDOI2014] 數表
給定 \(n,m,a\),求 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^m \sigma(\gcd(i,j))[\sigma(\gcd(i,j))\le a]\),\(T\) 組資料,\(n,m\le 10^5,T\le 2\times 10^4\)。
先考慮沒有 \(a\) 的限制:
列舉 \(T=di\):
令 \(f(x)=\sum\limits_{d\mid x} \sigma(d) \mu(\lfloor\frac{x}{d}\rfloor)\),此時只有當 \(\sigma(d)\le a\) 時,才會對 \(f(x)\) 產生貢獻。
於是可以按 \(a\) 從小到大對詢問排序,每次暴力加入所有 \(\sigma(d)\le a\) 的 \(d\),並更新 \(f(x)\)。由於求答案還需要知道 \(f\) 的字首和,所以用樹狀陣列維護即可。每個數插入的次數為調和級數,而插入一次時間複雜度為 \(\mathcal{O}(\log n)\),所以總時間複雜度就是 \(\mathcal{O}(n\log^2 n+T\sqrt n\log n)\)。
杜教篩
介紹:
杜教篩可以在 \(\mathcal{O}(n^\frac 2 3)\) 的時間複雜度中求出一類積性函式的字首和。假設 \(f\) 是一個積性函式,如果能找到另一個積性函式 \(g\) 使得 \(g\) 和\(f\ast g\) 的字首和都能快速求出,那麼就能用杜教篩求出 \(f\) 的字首和。
比如:
- 可以在 \(\mathcal{O}(1)\) 的時間內求出 \(1\) 和 \(\varepsilon\) 的字首和,而 \(\mu\ast I=\varepsilon\),所以可以用杜教篩求出 \(\mu\) 的字首和。
- 可以在 \(\mathcal{O}(1)\) 的時間內求出 \(1\) 和 \(Id\) 的字首和,而 \(\varphi\ast I=Id\),所以可以用杜教篩求出 \(\varphi\) 的字首和。
杜教篩:
現在要求積性函式 \(f\) 的字首和,令 \(S(n)=\sum\limits_{i=1}^n f(i)\)。
再找一個積性函式 \(g\),則 \(f\ast g\) 的字首和為:
接著考慮 \(g(1)S(n)\) 等於什麼,發現:
此時只需要找一個積性函式 \(g\) 使得 \(g\) 和 \(f\ast g\) 的字首和都可以快速求出,就可以數論分塊遞迴來求了。
虛擬碼:
ll sum_g(ll n);//g的字首和
ll sum_fg(ll n);//f*g的字首和
ll sum_f(ll n)
{
ll ans = sum_fg(n);
for(ll i = 2,j;i <= n;i = j+1)
{
j = n/(n/i);
ans -= (sum_g(j)-sum_g(i-1))*sum_f(n/i);
}
return ans;
}
杜教篩是數論分塊裡面遞迴,時間複雜度可以看作 \(\mathcal{O}(n^\frac 3 4)\),具體咋證的可以看以下式子感性理解:
其實可以預處理出前 \(m\) 個答案,然後再用杜教篩,時間複雜度就是:
一般為了平均,當 \(m=n^\frac 2 3\) 時,時間複雜度也是 \(\mathcal{O}(n^\frac 2 3)\)。
\(\mu,\varphi\) 的字首和
- \(\mu\ast I=\varepsilon\),而 \(I(n)\) 的字首和就是 \(n\),\(\varepsilon(n)\) 的字首和就是 \(1\)。
- \(\varphi\ast I=Id\),而 \(Id(n)\) 的字首和就是 \(\frac{n(n+1)}2\)。
程式碼中 \(smu,sphi\) 是提前篩好的 \(\mu\) 和 \(\varphi\) 的字首和,\(Smu,Sphi\) 是記憶化。
ll sum_mu(int n)
{
if(n < N)return smu[n];
if(Smu[n])return Smu[n];
ll ans = 1;
for(ll i = 2,j;i <= n;i = j+1)
{
j = n/(n/i);
ans -= (j-i+1)*sum_mu(n/i);
}
return Smu[n] = ans;
}
ll sum_phi(int n)
{
if(n < N)return sphi[n];
if(Sphi[n])return Sphi[n];
ll ans = n*(n+1ll)/2;
for(ll i = 2,j;i <= n;i = j+1)
{
j = n/(n/i);
ans -= (j-i+1)*sum_phi(n/i);
}
return Sphi[n] = ans;
}
擴充套件:
求 \(f(n)=\varphi(i)\times i\) 的字首和。
令 \(g=Id\),則:
所以 \(f\ast g\) 的字首和就是 \(\frac{n(n+1)(2n+1)} 6\)。
PN 篩
咕咕咕
Min25 篩
咕咕咕