题意
∑
i
=
1
n
∑
j
=
1
m
g
c
d
(
i
,
j
)
\sum_{i=1}^n\sum_{j=1}^mgcd(i,j)
i=1∑nj=1∑mgcd(i,j)
1
<
=
n
,
m
<
=
1
0
11
1<=n,m<=10^{11}
1<=n,m<=1011
思路
可以对式子进行一些变化如下
令
N
=
m
i
n
(
n
,
m
)
N=min(n,m)
N=min(n,m)
原
式
=
∑
i
=
1
N
∑
j
=
1
N
g
c
d
(
i
,
j
)
原式=\sum_{i=1}^N\sum_{j=1}^Ngcd(i,j)
原式=i=1∑Nj=1∑Ngcd(i,j)
=
∑
d
=
1
N
d
∑
i
=
1
N
∑
j
=
1
N
[
g
c
d
(
i
,
j
)
=
=
d
]
=\sum_{d=1}^Nd\sum_{i=1}^N\sum_{j=1}^N[gcd(i,j)==d]
=d=1∑Ndi=1∑Nj=1∑N[gcd(i,j)==d]
=
∑
d
=
1
N
d
∑
i
=
1
⌊
N
d
⌋
∑
j
=
1
⌊
N
d
⌋
[
g
c
d
(
i
,
j
)
=
=
1
]
=\sum_{d=1}^Nd\sum_{i=1}^{\left \lfloor \frac{N}{d} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{N}{d} \right \rfloor}[gcd(i,j)==1]
=d=1∑Ndi=1∑⌊dN⌋j=1∑⌊dN⌋[gcd(i,j)==1]
后面的部分可以用莫比乌斯反演转换为
O
(
n
)
O(\sqrt{n})
O(n),总复杂度就是为
O
(
n
n
)
O(n\sqrt{n})
O(nn),还是不可做,转换后为
=
∑
d
=
1
N
d
∑
i
=
1
⌊
N
d
⌋
μ
(
i
)
⌊
n
i
d
⌋
⌊
m
i
d
⌋
=\sum_{d=1}^Nd\sum_{i=1}^{\left \lfloor \frac{N}{d} \right \rfloor}\mu(i)\left \lfloor \frac{n}{id} \right \rfloor\left \lfloor \frac{m}{id} \right \rfloor
=d=1∑Ndi=1∑⌊dN⌋μ(i)⌊idn⌋⌊idm⌋
上式等价于
=
∑
d
=
1
N
d
∑
i
d
=
1
N
μ
(
i
)
⌊
n
i
d
⌋
⌊
m
i
d
⌋
=\sum_{d=1}^Nd\sum_{id=1}^{N}\mu(i)\left \lfloor \frac{n}{id} \right \rfloor\left \lfloor \frac{m}{id} \right \rfloor
=d=1∑Ndid=1∑Nμ(i)⌊idn⌋⌊idm⌋
令
T
=
i
d
T=id
T=id,对于每一个
T
T
T来说只有
i
=
T
d
i=\frac{T}{d}
i=dT,且
T
%
d
=
=
0
T\%d==0
T%d==0,带入得
=
∑
d
=
1
N
d
∑
T
=
1
N
[
T
%
d
=
=
0
]
μ
(
T
d
)
⌊
n
T
⌋
⌊
m
T
⌋
=\sum_{d=1}^Nd\sum_{T=1}^{N}[T\%d==0]\mu(\frac{T}{d})\left \lfloor \frac{n}{T} \right \rfloor\left \lfloor \frac{m}{T} \right \rfloor
=d=1∑NdT=1∑N[T%d==0]μ(dT)⌊Tn⌋⌊Tm⌋
由于
T
T
T只和
d
d
d有关,也可以认为是
T
T
T是
1
−
N
1-N
1−N中
d
d
d得倍数那么式子就可以变为
=
∑
d
=
1
N
d
∑
d
∣
T
N
μ
(
T
d
)
⌊
n
T
⌋
⌊
m
T
⌋
=\sum_{d=1}^Nd\sum_{d|T}^{N}\mu(\frac{T}{d})\left \lfloor \frac{n}{T} \right \rfloor\left \lfloor \frac{m}{T} \right \rfloor
=d=1∑Ndd∣T∑Nμ(dT)⌊Tn⌋⌊Tm⌋
把
d
d
d乘进去
=
∑
d
=
1
N
∑
d
∣
T
N
d
μ
(
T
d
)
⌊
n
T
⌋
⌊
m
T
⌋
=\sum_{d=1}^N\sum_{d|T}^{N}d\mu(\frac{T}{d})\left \lfloor \frac{n}{T} \right \rfloor\left \lfloor \frac{m}{T} \right \rfloor
=d=1∑Nd∣T∑Ndμ(dT)⌊Tn⌋⌊Tm⌋
我们可以改变枚举变量,原式枚举的是
d
d
d的倍数,已知在
1
−
N
1-N
1−N中枚举一个数的倍数和
1
−
N
1-N
1−N中枚举一个数的因子是等价的所以,我们可以把枚举
d
d
d的倍数改为枚举
T
T
T的因子,那么就有
=
∑
T
=
1
N
∑
d
∣
T
d
μ
(
T
d
)
⌊
n
T
⌋
⌊
m
T
⌋
=\sum_{T=1}^N\sum_{d|T}d\mu(\frac{T}{d})\left \lfloor \frac{n}{T} \right \rfloor\left \lfloor \frac{m}{T} \right \rfloor
=T=1∑Nd∣T∑dμ(dT)⌊Tn⌋⌊Tm⌋
如果你知道狄利克雷卷积的话会发现
∑
d
∣
T
d
μ
(
T
d
)
\sum_{d|T}d\mu(\frac{T}{d})
d∣T∑dμ(dT)是一个典型的卷积形式,可知
∑
d
∣
T
d
μ
(
T
d
)
=
i
d
∗
μ
\sum_{d|T}d\mu(\frac{T}{d})=id*\mu
d∣T∑dμ(dT)=id∗μ
其中
i
d
id
id为单位函数
i
d
(
n
)
=
n
id(n)=n
id(n)=n,
μ
\mu
μ为莫比乌斯函数
令
h
=
i
d
∗
μ
h=id*\mu
h=id∗μ
已知
μ
∗
I
=
e
\mu*I=e
μ∗I=e其中
e
e
e为元函数
e
(
n
)
=
[
n
=
=
1
]
e(n)=[n==1]
e(n)=[n==1],
I
I
I为恒等函数
I
(
n
)
=
1
I(n)=1
I(n)=1
那么有
h
∗
I
=
i
d
∗
μ
∗
I
h*I=id*\mu*I
h∗I=id∗μ∗I
h
∗
I
=
i
d
∗
e
h*I=id*e
h∗I=id∗e
h
∗
I
=
i
d
h*I=id
h∗I=id
又有
φ
∗
I
=
i
d
\varphi*I=id
φ∗I=id,所以
h
=
φ
h=\varphi
h=φ,
φ
\varphi
φ为欧拉函数,那么原式有
=
∑
T
=
1
N
φ
(
T
)
⌊
n
T
⌋
⌊
m
T
⌋
=\sum_{T=1}^N\varphi(T)\left \lfloor \frac{n}{T} \right \rfloor\left \lfloor \frac{m}{T} \right \rfloor
=T=1∑Nφ(T)⌊Tn⌋⌊Tm⌋
欧拉函数前缀和可以用杜教筛求得所以总的时间复杂度就可以在
O
(
n
2
3
)
O(n^{\frac{2}{3}})
O(n32)内解决了
推荐的题目有1237 最大公约数之和 V3
#include<bits/stdc++.h>
#include <unordered_map>
using namespace std;
typedef long long ll;
const int maxx=10000005;
const int mod=1000000007;
map<ll,ll> P;
bool isP[maxx];
int prime[maxx];
int cnt;
ll phi[maxx];
ll inv=500000004;
void init()
{
phi[1]=1;
for(int i=2;i<maxx;i++)
{
if(!isP[i]){prime[cnt++]=i;phi[i]=i-1;}
for(int j=0;j<cnt&&(ll)i*prime[j]<maxx;j++)
{
isP[i*prime[j]]=true;
if(i%prime[j])
phi[i*prime[j]]=phi[i]*(prime[j]-1);
else
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
}
}
for(int i=1;i<maxx;i++)
phi[i]=(phi[i]+phi[i-1])%mod;
}
ll Sum(ll x)
{
if(x<maxx)return phi[x];
if(P[x])return P[x];
ll ans=((x+1)%mod*(x%mod)%mod)*inv%mod;
for(ll i=2,last;i<=x;i=last+1)
{
last=x/(x/i);
ans=(ans-(last-i+1)%mod*Sum(x/i)%mod+mod)%mod;
}
ans=(ans+mod)%mod;
P[x]=ans;
return ans;
}
int main()
{
init();
long long n;
scanf("%lld",&n);
long long ans=0;
for(long long i=1,last;i<=n;i=last+1)
{
last=n/(n/i);
ans=(ans+(Sum(last)%mod-Sum(i-1)%mod+mod)%mod*((n/i)%mod)%mod*((n/i)%mod)%mod+mod)%mod;
}
printf("%lld\n",ans);
return 0;
}
/*
10000000000 10000000000
*/