这其实是我的第一道认真做的莫比乌斯反演题
经过观察发现,位于
(x,y)
(
x
,
y
)
的植物的能量损失为
gcd(x,y)−1
g
c
d
(
x
,
y
)
−
1
于是我们发现,原题实际上就是在让我们求
那么问题来了,我们该怎么求这个式子呢:
这时候我们就需要用到
莫比乌斯反演,说白了就是两个公式:
如果
f(n)=∑d|ng(d)
f
(
n
)
=
∑
d
|
n
g
(
d
)
,则
g(n)=∑d|nμ(d)∗f(nd)
g
(
n
)
=
∑
d
|
n
μ
(
d
)
∗
f
(
n
d
)
如果
f(n)=∑n|dg(d)
f
(
n
)
=
∑
n
|
d
g
(
d
)
,则
g(n)=∑n|dμ(dn)∗f(d)
g
(
n
)
=
∑
n
|
d
μ
(
d
n
)
∗
f
(
d
)
前者称为约数的莫比乌斯反演,后者称为倍数的莫比乌斯反演。其中的
μ(n)
μ
(
n
)
是莫比乌斯函数,
n
n
包含平方因子时,,否则
μ(n)=(−1)n的平方因子个数
μ
(
n
)
=
(
−
1
)
n
的
平
方
因
子
个
数
现在,让我们对原式作一个变形:
其中方括号表示括号内式子为真时值为一,否则为零。
现在不妨记 g(k)=∑ni=1∑mj=1[gcd(i,j)=d] g ( k ) = ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = d ]
然后我们可以构造出 f(k)=∑k|dg(d)=∑ni=1∑mj=1[k|gcd(i,j)] f ( k ) = ∑ k | d g ( d ) = ∑ i = 1 n ∑ j = 1 m [ k | g c d ( i , j ) ]
这时候,我们惊讶地发现: f(k)=⌊nk⌋⌊mk⌋ f ( k ) = ⌊ n k ⌋ ⌊ m k ⌋
于是此时,我们就可以使用倍数的莫比乌斯反演,Excalibur——————!!!
暴力累加就可以了
记得用long long
什么?你问我怎么算 μ(n) μ ( n ) ?
具体实现见代码如下:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
int n,m,p[100000],p_cnt,Mu[1000000];
bool flag[1000000];
void init()//线性筛求莫比乌斯函数
{
Mu[1]=1;
for(int i=2;i<=n;i++)
{
if(!flag[i])
{
Mu[i]=-1;
p[++p_cnt]=i;
}
for(int j=1;j<=p_cnt&&i*p[j]<=n;j++)
{
flag[i*p[j]]=1;
if(i%p[j]==0)
{
Mu[i*p[j]]=0;
break;
}
Mu[i*p[j]]=-Mu[i];
}
}
}
LL solve()
{
LL ret=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j*i<=n;j++)
{
ret+=1LL*i*Mu[j]*(n/(j*i))*(m/(j*i));
}
}
return ret;
}
int main()
{
cin>>n>>m;
if(m<n)swap(n,m);
init();
cout<<(solve()*2-1LL*n*m)<<endl;
return 0;
}