莫比乌斯反演
今天是世纪性的一天,因为我又又又又来看数论且弄懂了qwq。
前置知识:交换求和,整除分块(我们需要将式子化为整数分块可以解决的形式)
莫比乌斯函数
-> μ ( d ) \mu(d) μ(d)
函数构成
-
当 d = 1 d=1 d=1时, μ ( d ) = 1 \mu(d)=1 μ(d)=1
-
当 d = Π i = 1 k d=\Pi_{i=1}^k d=Πi=1k p i p_i pi,且 p i p_i pi为互异质数时, μ ( d ) = ( − 1 ) k \mu(d)=(-1)^k μ(d)=(−1)k;
(也就是就是 d d d分解质因数后,没有幂次大于2的质因子,此时函数值根据分解的个数决定) -
只要 d d d含有任何质因子的幂次大于等于2,则 μ ( d ) \mu(d) μ(d) = 0 =0 =0
性质
-
对于任意正整数 n n n, Σ d ∣ n \Sigma_{d|n} Σd∣n Σ d ∣ n \Sigma_{d|n} Σd∣n
-
对于任意正整数 n n n, Σ d ∣ n \Sigma_{d|n} Σd∣n μ ( d ) n \frac{\mu(d)}{n} nμ(d) = ϕ ( d ) n = \frac{\phi(d)}{n} =nϕ(d)
code
O ( n ) O(n) O(n)版本,如果超时请去学杜教筛
void get_mu(int n)
{
mu[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i]){prim[++cnt]=i;mu[i]=-1;}
for(int j=1;j<=cnt&&prim[j]*i<=n;j++)
{
vis[prim[j]*i]=1;
if(i%prim[j]==0)break;
else mu[i*prim[j]]=-mu[i];
}
}
}
注意
a ∣ b a|b a∣b的意思为b除以a为整数(b为a的倍数),即a能整除b
莫比乌斯反演
定理
F ( n ) F(n) F(n)和 f ( n ) f(n) f(n)是定义在非负整数集合上的两个函数,它们之间满足关系
F ( n ) = Σ d ∣ n f ( d ) F(n)=\Sigma_{d|n} f(d) F(n)=Σd∣nf(d)
那么就有结论
f ( n ) = Σ d ∣ n μ ( d ) F ( n d ) f(n)=\Sigma_{d|n} \mu(d) F(\frac{n}{d}) f(n)=Σd∣nμ(d)F(dn)
这个定理即为莫比乌斯反演定理.
还有另外一种形式
若
F ( n ) = Σ n ∣ d f ( d ) F(n)=\Sigma_{n|d} f(d) F(n)=Σn∣df(d)
则
f ( n ) = Σ n ∣ d μ ( d n ) F ( d ) f(n)=\Sigma_{n|d}\mu(\frac{d}{n})F(d) f(n)=Σn∣dμ(nd)F(d)
证明
这里只给出第一种形式的证明,第二种形式同理.
由定理可设
F ( n d ) = Σ i ∣ n d f ( i ) F(\frac{n}{d})=\Sigma_{i|\frac{n}{d}} f(i) F(dn)=Σi∣dnf(i)
Σ d ∣ n μ ( d ) F ( n d ) = Σ d ∣ n μ ( d ) Σ i ∣ n d f ( i ) \Sigma_{d|n} \mu(d)F(\frac{n}{d})=\Sigma_{d|n} \mu(d) \Sigma_{i|\frac{n}{d}} f(i) Σd∣nμ(d)F(dn)=Σd∣nμ(d)Σi∣dnf(i)
= Σ d i ∣ n μ ( d ) f ( i ) =\Sigma_{di|n}\mu(d) f(i) =Σdi∣nμ(d)f(i)//这一步没看懂的去看交换求和,接下来都为交换求和的知识点
= Σ i ∣ n Σ d ∣ n i μ ( d ) f ( i ) =\Sigma_{i|n}\Sigma_{d|\frac{n}{i}}\mu(d) f(i) =Σi∣nΣd∣inμ(d)f(i)
= Σ i ∣ n f ( i ) Σ d ∣ n i μ ( d ) =\Sigma_{i|n}f(i)\Sigma_{d|\frac{n}{i}}\mu(d) =Σi∣nf(i)Σd∣inμ(d)
= Σ i ∣ n f ( i ) Σ d ∣ n i ( μ ( d ) = [ n i = 1 ] ) =\Sigma_{i|n}f(i)\Sigma_{d|\frac{n}{i}}(\mu(d)=[\frac{n}{i}=1]) =Σi∣nf(i)Σd∣in(μ(d)=[in=1])
//(莫比乌斯函数性质1)只有在 n i = 1 \frac{n}{i}=1 in=1时才有值,其他时候为0;
//因此 n = i n=i n=i
//故 Σ i ∣ n f ( i ) = f ( n ) \Sigma_{i|n}f(i)=f(n) Σi∣nf(i)=f(n)
= f ( n ) =f(n) =f(n)
得证.
例题
P2257 YY的GCD - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
观察定理可知,我们在反演前需要设出 F ( n ) F(n) F(n)与 f ( d ) f(d) f(d)
而对于这种有 g c d gcd gcd的题目,一般套路为将 f ( d ) f(d) f(d)设为 g c d ( i , j ) gcd(i,j) gcd(i,j) = d =d =d的对数,将 F ( n ) F(n) F(n)设为 g c d ( i , j ) = n gcd(i,j)=n gcd(i,j)=n或n的倍数的对数;
(对数为满足条件的 ( i , j ) (i,j) (i,j)对数)
即有
f ( d ) = Σ i = 1 n Σ j = 1 m [ g c d ( i , j ) = d ] f(d)=\Sigma_{i=1}^n\Sigma_{j=1}^m[gcd(i,j)=d] f(d)=Σi=1nΣj=1m[gcd(i,j)=d]
F ( n ) = Σ n ∣ d f ( d ) = ⌊ N n ⌋ ⌊ M n ⌋ F(n)=\Sigma_{n|d}f(d)=\lfloor \frac{N}{n}\rfloor\lfloor \frac{M}{n}\rfloor F(n)=Σn∣df(d)=⌊nN⌋⌊nM⌋
带入反演公式后有
f ( n ) = Σ n ∣ d μ ( d n ) F ( d ) f(n)=\Sigma_{n|d}\mu(\frac{d}{n})F(d) f(n)=Σn∣dμ(nd)F(d)
接下来开始计算答案
a n s = Σ k ∈ p r Σ i = 1 n Σ j = 1 m [ g c d ( i , j ) = k ] ans=\Sigma_{k\in pr}\Sigma_{i=1}^n\Sigma_{j=1}^m[gcd(i,j)=k] ans=Σk∈prΣi=1nΣj=1m[gcd(i,j)=k]
= Σ k ∈ p r f ( k ) =\Sigma_{k\in pr}f(k) =Σk∈prf(k)//反演
= Σ k ∈ p r Σ k ∣ d μ ( d k ) F ( d ) =\Sigma_{k\in pr}\Sigma_{k|d}\mu(\frac{d}{k})F(d) =Σk∈prΣk∣dμ(kd)F(d)
为了将 d d d消去,设 d k = v \frac{d}{k}=v kd=v
= Σ k ∈ p r Σ v = 1 m i n ( ⌊ n k ⌋ , ⌊ m k ⌋ ) μ ( v ) F ( v k ) =\Sigma_{k \in pr}\Sigma_{v=1}^{min(\lfloor \frac{n}{k}\rfloor,\lfloor \frac{m}{k}\rfloor)}\mu(v)F(vk) =Σk∈prΣv=1min(⌊kn⌋,⌊km⌋)μ(v)F(vk)
= Σ k ∈ p r Σ v = 1 m i n ( ⌊ n k ⌋ , ⌊ m k ⌋ ) μ ( v ) ⌊ m v k ⌋ ⌊ n v k ⌋ =\Sigma_{k \in pr}\Sigma_{v=1}^{min(\lfloor \frac{n}{k}\rfloor,\lfloor \frac{m}{k}\rfloor)}\mu(v)\lfloor \frac{m}{vk}\rfloor\lfloor \frac{n}{vk}\rfloor =Σk∈prΣv=1min(⌊kn⌋,⌊km⌋)μ(v)⌊vkm⌋⌊vkn⌋
= Σ k ∈ p r Σ v k = 1 m i n ( n , m ) μ ( v ) ⌊ m v k ⌋ ⌊ n v k ⌋ =\Sigma_{k \in pr}\Sigma_{vk=1}^{min(n,m)}\mu(v)\lfloor \frac{m}{vk}\rfloor\lfloor \frac{n}{vk}\rfloor =Σk∈prΣvk=1min(n,m)μ(v)⌊vkm⌋⌊vkn⌋
由于我们需要将式子向整除分块,即形如 Σ i = 1 n ⌊ n i ⌋ \Sigma_{i=1}^n \lfloor\frac{n}{i}\rfloor Σi=1n⌊in⌋的形式
所以我们设 T = v k T=vk T=vk
= Σ k ∈ p r Σ T = 1 m i n ( n , m ) μ ( T k ) ⌊ m T ⌋ ⌊ n T ⌋ =\Sigma_{k \in pr}\Sigma_{T=1}^{min(n,m)}\mu(\frac{T}{k})\lfloor \frac{m}{T}\rfloor\lfloor \frac{n}{T}\rfloor =Σk∈prΣT=1min(n,m)μ(kT)⌊Tm⌋⌊Tn⌋
= Σ T = 1 m i n ( n , m ) ⌊ m T ⌋ ⌊ n T ⌋ Σ k ∈ p r , k ∣ T μ ( T k ) =\Sigma_{T=1}^{min(n,m)}\lfloor \frac{m}{T}\rfloor\lfloor \frac{n}{T}\rfloor\Sigma_{k \in pr,k|T}\mu(\frac{T}{k}) =ΣT=1min(n,m)⌊Tm⌋⌊Tn⌋Σk∈pr,k∣Tμ(kT)
接下来就可以开始运算啦
g g g为 Σ k ∈ p r , k ∣ T μ ( T k ) \Sigma_{k \in pr,k|T}\mu(\frac{T}{k}) Σk∈pr,k∣Tμ(kT),即 g [ T ] g[T] g[T]
s u m sum sum为 g g g的前缀和,用来计算整除分块.
code
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e7+10;
ll g[N],sum[N],mu[N];
int T,n,m,pr[N],cnt;
bool st[N];
void get_mu()
{
mu[1]=1;
for(int i=2;i<=N;++i)
{
if(!st[i])mu[i]=-1,pr[++cnt]=i;
for(int j=1;j<=cnt&&i*pr[j]<=N;++j)
{
st[i*pr[j]]=true;
if(i%pr[j]==0)break;
else mu[i*pr[j]]=-mu[i];
}
}
for(int i=1;i<=cnt;++i)
for(int j=1;j*pr[i]<=N;++j)
g[1ll*pr[i]*j]+=mu[j];
for(int i=1;i<=N;++i)sum[i]=sum[i-1]+g[i];
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
get_mu();
cin>>T;
while(T--)
{
cin>>n>>m;
if(n>m)swap(n,m);
ll ans=0;
for(int l=1,r;l<=n;l=r+1)
{
r=min(n/(n/l),m/(m/l));
ans+=1ll*(m/l)*(n/l)*(sum[r]-sum[l-1]);
}
cout<<ans<<'\n';
}
return 0;
}
日拱一卒,功不唐捐!