《關於上一次講課莫比烏斯反演出鍋了所以整理一下那些事》
上次講課用莫比烏斯反演的時候講出鍋了,所以總結一下
前置芝士
整除分塊
----轉載自dalao部落格
問題:求\(\sum_{i=1}^N \lfloor \frac Ni \rfloor\),其中\(N \leq 10^{12}\)
對於\(\large \lfloor \frac Ni \rfloor\)最多可存在\(2\sqrt{N}\)種取值
可以分類討論\(i\)的取值,當\(i\le \sqrt{N}\)時,存在\(\sqrt{N}\)種取值,而對於\(i\gt\sqrt{N},\large{\frac Ni}\lt\sqrt{N}\),最多也僅有\(\sqrt{N}\)種取值,所以最多可存在\(2\sqrt{N}\)
另外的話設\(\large \lfloor \frac N{i'} \rfloor\) 與 \(\large \lfloor \frac Ni \rfloor\)相等,那麼對於\(i'\)最大值為\(\large \left \lfloor \frac N{\left \lfloor \frac Ni \right \rfloor\ } \right \rfloor\)
證明的話我們對於\(\large{ \lfloor \frac Ni \rfloor}=k\),可以轉化為\(ki+r=N\),其中的\(1\le\ r\lt\ i\),那麼對於\(\large{\lfloor \frac N{i+d} \rfloor}=k\)
於是可以算出\(\begin{aligned}i'=i+d_{max} =i+\lfloor \frac rk \rfloor =i+\left \lfloor \frac {N \;mod\; i}{\lfloor \frac Ni \rfloor} \right \rfloor =i+\left \lfloor \frac {N-\lfloor \frac Ni\rfloor i}{\lfloor \frac Ni \rfloor} \right \rfloor =\left \lfloor i + \frac {N-\lfloor \frac Ni\rfloor i}{\lfloor \frac Ni \rfloor} \right \rfloor =\left \lfloor \frac{\lfloor \frac Ni \rfloor i}{\lfloor \frac Ni \rfloor} + \frac {N-\lfloor \frac Ni\rfloor i}{\lfloor \frac Ni \rfloor} \right \rfloor =\left \lfloor \frac N{\lfloor \frac Ni \rfloor} \right \rfloor \quad \quad\end{aligned}\)
然後可以列舉兩個變數\(l,r\),其中\(l\)初始值為1,每次可以令\(\large r=\left \lfloor \frac N{\lfloor \frac NL \rfloor} \right \rfloor\),隨後將\(\large (r-l+1)\cdot \lfloor \frac NL \rfloor\)對答案進行累加,隨後令\(l=r+1\),依次增加累加,最後對於分塊複雜度可以看為\(O(\sqrt N)\)的
積性函式
之前我所說的可能有錯現在從新進行一次宣告吧算是,對於任意 \(x,y \in \mathbb{N}_{+},\gcd(x,y)=1\),都有\(f(xy)=f(x)f(y)\),則\(f(n)\)為積性函式
若\(f(n)\),\(g(n)\)為積性函式,則以下的情況也為積性函式
\(\begin{aligned}h(x)=&f(x^p)\\h(x)=&f^p(x)\\h(x)=&f(x)g(x)\\h(x)=&\sum_{d\mid x}f(d)g(\frac{x}{d})\end{aligned}\)
積性函式的例子:\(e(n)=[n=1]\)
\(1(n)=1\)
\(\mu(n)=\begin{cases}(-1)^k&n=p_1p_2p_3\dots p_k\\0&n=p^2q\\1&n=1\end{cases}\)
\(\varphi(n)=\sum_{i=1}^n[\gcd(i,n)=1]\)
\(\operatorname{id}_k(n)=n^k\operatorname{id}_{1}(n)\)
狄利克雷Dirichlet卷積
定義(不是推出來的是定義):定義兩個數論函式\(f,g\)卷積為\((f*g)(n)=\sum_{d|n}f(d)g(\frac nd)\)
一些性質
卷積滿足交換律和結合律
數論函式\(e\)為卷積中的單位元即任何函式卷\(e\)都為其本身
栗子:\(\mu*id_0=\epsilon\)
\(\varphi*id_0=id_1\)
\(\mu*id_1=\varphi\)
\(id_0*id_1=σ\)
莫比烏斯函式
\(\mu(n)=\begin{cases}(-1)^k&k為n的本質不同質因子個數\\0&n含有平方因子\\1&n=1\end{cases}\)
性質
是積性函式
\(\sum_{d\mid n}\mu(d)=\begin{cases}1&n=1\\0 & n≠1\\ \end{cases}\)
即為\(\mu*id_0=\epsilon\)
證明的話不會,就這樣
線性篩\(\mu\)應該都知道吧
inline void pri(){
for(int i = 2;i <= N;i ++){
if(!ispri[i]){
prime[++ cnt] = i;
mu[i] =- 1;
}
for(int j = 1;j <= cnt && (i * prime[j] <= N);j ++){
ispri[i*prime[j]] = true;
if(i % prime[j]==0){
break;
}
else{
mu[i * prime[j]] =- mu[i];
}
}
}
但是我會證明\(\mu*id_1=\varphi\)下面是證明
\(\begin{aligned}\varphi*id_0&=\sum_{d\mid n}\varphi(\frac{n}{d})\\&=\sum_{i=0}^c\varphi(p^1)\\&=p^c\\&=id_1\end{aligned}\)
在等式兩邊同時捲上一個\(\mu\)就可以得到\(\varphi(n)=\sum_{d\mid n}d*\mu(\frac{n}{d})\)
即為\(\mu*id_1=\varphi\)
正文:莫比烏斯反演
設有\(f(n)\),\(g(n)\)兩個數論函式
若存在\(f(n)=\sum_{d|n}g(d)\iff g(n)=\sum_{d|n}\mu(\frac nd)f(d)\)
其實並沒有什麼用處,相當於是廢話,證明的話你可以看作\(f=g*1\),然後證明\(g=f*\mu\)
在\(f=g*1\)兩邊同時捲上一個\(\mu\)之後你可以得到\(f*\mu=g*1*\mu\)即為\(f*\mu=g*e\),則可得出\(g=f*\mu\)
題目的話
UVA11426 拿行李(極限版) GCD - Extreme (II)
\[\sum_{i=1}^{n}\sum_{j=i+1}^{n}\gcd(i,j) \]
你會發現在計算j時重複計算了i的那麼我們考慮先將其看作單獨的i,j,隨後將重複部分減去即可
\(\begin{aligned}\sum_{i = 1}^n\sum_{j = 1}^n\gcd(i, j)= \sum_{d = 1}^nd\sum_{i = 1}^n\sum_{j = 1}^n[\gcd(i, j) = d]\end{aligned}\)
到了這裡,我們發現對於\([gcd(i,j)=1]\)我們可以根據莫比烏斯函式的定義\(\begin{aligned}\sum_{d\mid n}\mu(d)\ =[n=1]\end{aligned}\)來進行替換,即\(\begin{aligned}\sum_{d=1}^n\sum_{i=1}^\frac{n}{d}\sum_{j=1}^\frac{n}{d}\sum_{p\mid gcd(i,j)}\mu(p)\end{aligned}\)
我們可以按照套路將\(p\)提前,變換求和順序,先列舉\(d\mid gcd(i,j)\) 可得\(\begin{aligned}\sum_{d=1}^n\sum_{p=1}^\frac{n}{d}\mu(p)\sum_{i=1}^\frac{n}{d}[p\mid i]\sum_{j=1}^\frac{n}{d}[p\mid j]\end{aligned}\)
易知\(1\sim\lfloor\dfrac{n}{d}\rfloor\)中p的倍數有個\(\lfloor\dfrac{n}{dp}\rfloor\),故原式化為對於後面的i,j兩個和我們進行整除分塊來做\(\begin{aligned}\sum_{d = 1}^nd\sum_{p=1}^{\left\lfloor\frac n d\right\rfloor}\mu(p)\left\lfloor\frac n {dp}\right\rfloor\left\lfloor\frac n {dp}\right\rfloor\end{aligned}\)
這裡運用一個dp化Q的技巧可以變為\(\begin{aligned}\sum_{Q = 1}^n\sum_{d|Q}d*\mu(\frac Q{d})\left\lfloor\frac n {Q}\right\rfloor^2\end{aligned}\)
然後你會發現我們化簡到的\(\begin{aligned}\sum_{d|Q}d*\mu(\frac Q{d})\end{aligned}\)符合\(id*\mu=\varphi\)的形式,所以我們可以進一步簡化為\(\begin{aligned}\sum_{Q = 1}^n\varphi(Q)\left\lfloor\frac n {Q}\right\rfloor^2\end{aligned}\),對於詢問T次值,總下來複雜度為\(O(n +T\sqrt n)\),可以通過此題,上面那個閹割版的柿子一模一樣,照著用程式碼實現即可,此題最後還要處理一下重複情況
#include<bits/stdc++.h>
#define LL long long
using namespace std;
template <typename T> void read(T & t) {
t = 0;int f = 1;char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-')f =- 1;ch = getchar();}
do{t = t * 10 + ch - '0';ch = getchar();}while(ch >= '0' && ch <= '9');t *= f;
}
const int kato = 4e6 + 1;
bool ispri[kato];
LL n;
LL prime[kato] , phi[kato] , sum[kato] , cnt;
inline void get_phi(){
for(int i = 2;i <= kato;i ++){
if(!ispri[i]){
prime[++ cnt] = i;
phi[i] = i - 1;
}
for(int j = 1;j <= cnt && (i * prime[j] <= kato);j ++){
ispri[i * prime[j]] = 1;
if(i % prime[j] == 0){
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
else{
phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
}
for(int i = 1;i <= kato;i ++){
// if(i<=10) cerr<<phi[i]<<"\n";
sum[i] = sum[i - 1] + phi[i];
}
}
inline int Ame_(){
phi[1] = 1 , ispri[1] = 1;
get_phi();
while(cin >> n){
if(!n){
return 0;
}
LL ans = 0;
for(LL l = 1 , r;l <= n;l = r + 1){
r = n / (n / l);
ans += (sum[r] - sum[l - 1]) * (n / l) * (n / l);
}
ans -= n * (n + 1) / 2;
ans /= 2;
printf("%lld\n" , ans);
}
return 0;
}
int Ame__ = Ame_();
signed main(){;}
題目所給為\(\begin{aligned}\sum_{i=1}^n\sum_{j=1}^m[gcd(x,y)\in prime]\end{aligned}\)
\(\begin{aligned}=\sum_{p\in prime}\sum_{i=1}^n\sum_{j=1}^m[gcd(x,y)=p]\end{aligned}\)
\(\begin{aligned}=\sum_{p\in prime}\sum_{i=1}^n\sum_{j=1}^m[gcd(\frac{x}{p},\frac{y}{p})=1]\end{aligned}\)
\(\begin{aligned}=\sum_{p\in prime}\sum_{i=1}^\frac{n}{p}\sum_{j=1}^\frac{m}{p}[gcd(x,y)=1]\end{aligned}\)
到了這裡,我們發現對於\([gcd(i,j)=1]\)我們可以根據莫比烏斯函式的定義\(\begin{aligned}\sum_{d\mid n}\mu(d)\ =[n=1]\end{aligned}\)來進行替換,即
\(\begin{aligned}\sum_{p\in prime}\sum_{i=1}^\frac{n}{p}\sum_{j=1}^\frac{m}{p}\sum_{d\mid i,j}\mu(d)\end{aligned}\)
然後重點來了,你粗略地看著個柿子可以看為\(\begin{aligned}\sum_{p}\sum_{i}\sum_{j}\sum_{d=1}\mu(d)[d\mid i][d\mid j]\end{aligned}\),其中對\(\mu(d)\)有影響的為\(p\)可以提到\(i\)前面,\([d\mid i]\),\([d\mid j]\)同理可得,則有下一步柿子
\(\begin{aligned}\sum_{p\in prime}\sum_{d=1}^\frac{n}{p}\mu(d)\sum_{i=1}^\frac{n}{p}[d\mid i]\sum_{j=1}^\frac{m}{p}[d\mid j]\end{aligned}\)
然後用之前所學過的整除分塊對\([d\mid i]\), \([d\mid j]\)處理一下
\(\begin{aligned}\sum_{p\in prime}\sum_{d=1}^\frac{n}{p}\mu(d)\left \lfloor \frac{n}{dp} \right \rfloor\left \lfloor \frac{m}{dp} \right \rfloor\end{aligned}\)
將dp用k更換之後有\(\begin{aligned}\sum_{k=1}^n\sum_{p\in prime}\mu( \frac{k}{p} )\left \lfloor \frac{n}{k} \right \rfloor\left \lfloor \frac{m}{k} \right \rfloor\end{aligned}\)
最後在篩的時候維護一個字首和即可
#include<bits/stdc++.h>
#define LL long long
using namespace std;
template <typename T> void read(T & t){
t = 0;int f = 1;char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-')f =- 1;ch = getchar();}
do{t = t * 10 + ch - '0';ch = getchar();}while(ch >= '0' && ch <= '9');t *= f;
}
const int kato = 1e7 + 10;
int prime[kato >> 1] , cnt , t;
int mu[kato] , num[kato];
bool ispri[kato];
inline int my_swap(int &x , int &y){
return x ^= y ^= x ^= y ;
}
inline void pri(){
for(int i = 2;i <= kato - 10;i ++){
if(!ispri[i]){
prime[++ cnt] = i;
mu[i] =- 1;
}
for(int j = 1;j <= cnt && (i * prime[j] <= kato - 10);j ++){
if(i * prime[j] <= kato - 10){
ispri[i * prime[j]] = 1;
}
if(i % prime[j] == 0){
break;
}
else{
mu[i * prime[j]] =- mu[i];
}
}
}
for(int i = 1;i <= cnt;i ++){
int res = 1;
for(int j = prime[i];j <= kato - 1;j += prime[i] , res ++){
num[j] += mu[res];
}
}
for(int i = 2;i <= kato - 10;i ++){
num[i] += num[i - 1];
}
}
inline int Ame_(){
mu[1] = 1;
pri();
read(t);
for(int l , r , n , m; t --> 0 ;){
read(n);read(m);
LL ans = 0;
if(n > m){
my_swap(n , m);
}
for(l = 1 , r;l <= n;l = r + 1){
r = min(n / (n / l) , m / (m / l));
ans += 1LL * (num[r] - num[l - 1]) * (n / l) * (m / l);
}
printf("%lld\n" , ans);
}
return 0;
}
int Ame__ = Ame_();
int main(){;}