# 什么是莫比乌斯反演

## 关于莫比乌斯反演

F ( n ) = ∑ d ∣ n f ( d ) F(n)=\sum_{d|n} f(d)

f ( n ) = ∑ d ∣ n μ ( d ) F ( n d ) f(n)=\sum_{d|n} \mu(d)F(\frac{n}{d})

F ( n ) = ∑ n ∣ d f ( d ) F(n)=\sum_{n|d}f(d)

f ( n ) = ∑ n ∣ d μ ( d n ) F ( d ) f(n)=\sum_{n|d}\mu(\frac{d}{n})F(d)

## 两条性质

1.如果 n &gt; 1 n&gt;1 n n 为正整数，则有：

∑ d ∣ n μ ( d ) = 0 \sum_{d|n}\mu(d)=0

2.对于任意正整数 n n 均有：

∑ d ∣ n μ ( d ) d = ϕ ( n ) n \sum_{d|n}\frac{\mu(d)}{d}=\frac{\phi(n)}{n}

## 证明莫比乌斯反演

∑ d ∣ n μ ( d ) F ( n d ) = ∑ d ∣ n μ ( d ) ∑ d ′ ∣ n d f ( d ′ ) \sum_{d|n}\mu(d)F(\frac{n}{d})=\sum_{d|n}\mu(d)\sum_{d&#x27;|\frac{n}{d}}f(d&#x27;)

∑ d ∣ n μ ( d ) ∑ d ′ ∣ n d f ( d ′ ) = ∑ d ′ ∣ n f ( d ′ ) ∑ d ∣ n d ′ μ ( d ) \sum_{d|n}\mu(d)\sum_{d&#x27;|\frac{n}{d}}f(d&#x27;)=\sum_{d&#x27;|n}f(d&#x27;)\sum_{d|\frac{n}{d&#x27;}}\mu(d)

∑ d ∣ n μ ( d ) F ( n d ) = ∑ d ′ ∣ n f ( d ′ ) ∑ d ∣ n d ′ μ ( d ) = f ( n ) \sum_{d|n}\mu(d)F(\frac{n}{d})=\sum_{d&#x27;|n}f(d&#x27;)\sum_{d|\frac{n}{d&#x27;}}\mu(d)=f(n)

# 莫比乌斯反演的应用

## 例题：HDU1695

f(t)=满足gcd(x,y)=t的数对个数，则F（t）和f(t)就存在莫比乌斯反演的关系了。显然F（t）=(b/t)*(d/t)

f ( 1 ) = ∑ d l i m μ ( d ) ∗ F ( d ) f(1)=\sum_d^{lim}\mu(d)*F(d)

#include<iostream>
#include<cstdio>
#include<climits>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=100005;
int T,a,b,c,d,e,tot;
long long ans1,ans2;
bool is[maxn];
int pri[maxn],miu[maxn];
void init(){//首先把莫比乌斯函数筛出来
miu[1]=1;
for(int i=2;i<=100000;i++){
if(!is[i]){pri[++tot]=i;miu[i]=-1;}
for(int j=1;j<=tot;j++){
int k=pri[j]*i;if(k>100000)break;
is[k]=1;
if(i%pri[j]==0){miu[k]=0;break;}
else miu[k]=-miu[i];
}
}
}
int main()
{
int i,j,cnt=0;
init();
scanf("%d",&T);
while(T--){
cnt++;ans1=ans2=0;
scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
if(!e){ printf("Case %d: 0\n",cnt);continue;}
b/=e;d/=e;//如果gcd(x,y)=1,那么gcd(x*e,y*e)=e;
if(b>d)swap(b,d);
for(i=1;i<=b;i++)ans1+=(long long)miu[i]*(b/i)*(d/i);
for(i=1;i<=b;i++)ans2+=(long long)miu[i]*(b/i)*(b/i);
printf("Case %d: %lld\n",cnt,ans1-ans2/2);
}
return 0;
}


for(i=1;i<=a;i=j+1){
j=min(a/(a/i),b/(b/i));
ans+=(long long)(sum[j]-sum[i-1])*(a/i)*(b/i);
//sum是miu的前缀和
}


## 例题：bzoj2301/洛谷2522 problem b

ans=find(b/k,d/k)-find((a-1)/k,d/k)-find((c-1)/k,b/k)+find((a-1)/k,(c-1)/k);


for(i=1;i<=min(x,y);i=j+1){
j=min(x/(x/i),y/(y/i));
re+=(long long)(sum[j]-sum[i-1])*(x/i)*(y/i);
}


## 例题：bzoj2820/洛谷P2257 YY的GCD

a n s = ∑ i s p r i m e ( p ) n ∑ i n ( n i p ) ( m i p ) μ ( i ) ans=\sum_{isprime(p)}^n \sum_i^n ( \frac{n}{ip})(\frac{m}{ip})\mu(i)

a n s = ∑ T n ( n T ) ( m T ) ∑ p ∣ T 且 i s p r i m e ( p ) μ ( T p ) ans=\sum_T^n ( \frac{n}{T})(\frac{m}{T}) \sum_{p|T且isprime(p)} \mu(\frac{T}{p})

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
#define ll long long
int q=0;char ch=' ';
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')q=q*10+ch-'0',ch=getchar();
return q;
}
const int maxn=10000005;
int n,m,T,tot,lim=10000000;
bool is[maxn];ll sum[maxn];
int pri[maxn>>1],mu[maxn];
void init(){
int i,j,p;ll k;
mu[1]=1;
for(i=2;i<=lim;i++){
if(!is[i]){pri[++tot]=i;mu[i]=-1;}
for(j=1;j<=tot;j++){
k=(ll)i*pri[j];if(k>lim)break;
is[k]=1;
if(i%pri[j])mu[k]=-mu[i];
else break;
}
}
for(i=1;i<=tot;i++)//预处理前缀和的办法
for(j=1;pri[i]*j<=lim;j++)sum[pri[i]*j]+=mu[j];
for(i=1;i<=lim;i++)sum[i]=sum[i-1]+sum[i];
}
int main()
{
while(T--){
if(n>m)swap(n,m);
ll ans=0;
for(int i=1,j;i<=n;i=j+1){
j=min(n/(n/i),m/(m/i));//一毛一样的优化
ans+=(ll)(n/i)*(ll)(m/i)*(ll)(sum[j]-sum[i-1]);
}
printf("%lld\n",ans);
}
return 0;
}


## 例题：bzoj2005/洛谷1447 能量采集

dalao们的题解经常长这样：水题，贴代码

1.容易意会得到，一颗坐标为(x,y)植物连线上的植物数量就是gcd(x,y)-1;

2.首先有一条结论：一个数的所有因子的欧拉函数之和等于这个数本身。

3.随便交换律一下得到： ∑ d = 1 n ∑ i = 1 n [ d ∣ n ] ∑ j = 1 m [ d ∣ m ] ϕ ( d ) ∗ ( n / i ) ∗ ( m / i ) \sum_{d=1}^n \sum_{i=1}^n[d|n] \sum_{j=1}^m[d|m]\phi(d)*(n/i)*(m/i)

4.现在求起来就方便多了，不过呢，还有一个优化，对于一个数i来说，设它的 n / i = k 1 , m / i = k 2 n/i=k_1,m/i=k_2 ，则同样满足 n / j = k 1 , m / j = k 2 n/j=k_1,m/j=k_2 的最大 j = m i n ( n / k 1 , m / k 2 ) ; j=min(n/k_1,m/k_2);

5.最后把得到的结果乘以2再减去m*n即可

#include<iostream>
#include<cstdio>
#include<climits>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll long long
ll n,m,ans;int tot;
bool is[1000010];
int pri[1000010],phi[10000100];
ll sum[1000010];
void init(){
ll i,j,k;
phi[1]=1;
for(i=2;i<=n;i++){
if(!is[i]){phi[i]=i-1;pri[++tot]=i;}
for(j=1;j<=tot;j++){
k=pri[j]*i;if(k>n)break;
is[k]=1;
if(i%pri[j]==0){phi[k]=(ll)phi[i]*pri[j];break;}
else phi[k]=(ll)(pri[j]-1)*phi[i];
}
}
for(i=1;i<=n;i++)sum[i]=sum[i-1]+phi[i];
}
int main()
{
ll i,j;
scanf("%lld%lld",&n,&m);
if(n>m)swap(n,m);
init();
for(i=1;i<=n;i=j+1){
j=min(m/(m/i),n/(n/i));
ans+=(ll)(sum[j]-sum[i-1])*(m/i)*(n/i);
}
ans=(ll)ans*2-(ll)n*m;
printf("%lld",ans);
return 0;
}


## 其他练习

bzoj2154/bzoj2693/洛谷P1829 Crash的数字表格:题解戳我QvQ

bzoj3994/洛谷P3327 约数个数和:题解戳我QvQ

bzoj3529/洛谷P3312 数表:题解戳我QvQ

bzoj4816/洛谷P3704/loj2000 数字表格:虽然利用莫比乌斯反演的方法很常规，但是这种相乘的变化还是挺新鲜的。

10-10 2948

09-13 95
05-22 1630
04-16 1134
08-04 2707
04-22 575
12-30 1002
07-30 666
06-01 2461
02-01 430
01-07 160
02-24 211
08-10 3174
09-18 1467
05-17 1384
05-03 268
09-19 571