题目大意
给出一个正整数
n
n
n,求
∑
i
=
1
n
∑
j
∣
i
gcd
(
j
,
i
j
)
\sum_{i=1}^n\sum_{j|i}\gcd(j,\dfrac{i}{j})
∑i=1n∑j∣igcd(j,ji)。
对于
20
%
20\%
20%的数据,
n
≤
1
0
5
n \leq 10^5
n≤105;
对于
50
%
50\%
50%的数据,
n
≤
1
0
7
n \leq 10^7
n≤107;
对于
80
%
80\%
80%的数据,
n
≤
1
0
10
n \leq 10^{10}
n≤1010;
对于
100
%
100\%
100%的数据,
n
≤
1
0
11
n \leq 10^{11}
n≤1011。
分析
这是一道数论题。题目中给出的式子不好直接算,于是我们要化简它。
化简式子
令
k
=
i
j
k=\dfrac{i}{j}
k=ji,并先枚举
k
k
k,再枚举
j
j
j,则
原
式
=
∑
k
=
1
∑
j
=
1
gcd
(
j
,
k
)
[
j
k
≤
n
]
原式=\sum_{k=1}\sum_{j=1}\gcd(j,k)[jk \leq n]
原式=k=1∑j=1∑gcd(j,k)[jk≤n]
因为要满足
j
k
≤
n
jk \leq n
jk≤n,所以
k
≤
n
k \leq n
k≤n,
j
≤
⌊
n
k
⌋
j \leq \lfloor \dfrac{n}{k} \rfloor
j≤⌊kn⌋,即
原
式
=
∑
k
=
1
n
∑
j
=
1
⌊
n
k
⌋
gcd
(
j
,
k
)
原式=\sum_{k=1}^{n}\sum_{j=1}^{\lfloor \frac{n}{k} \rfloor}\gcd(j,k)
原式=k=1∑nj=1∑⌊kn⌋gcd(j,k)
考虑枚举
gcd
\gcd
gcd函数的值,因为对于乘积小于等于
n
n
n的两正整数的最大公约数小于等于
n
\sqrt{n}
n,所以有
原
式
=
∑
i
=
1
⌊
n
⌋
i
∑
k
=
1
n
∑
j
=
1
⌊
n
k
⌋
[
gcd
(
j
,
k
)
=
i
]
原式=\sum_{i=1}^{\lfloor \sqrt{n} \rfloor}i\sum_{k=1}^n\sum_{j=1}^{\lfloor \frac{n}{k} \rfloor}[\gcd(j,k)=i]
原式=i=1∑⌊n⌋ik=1∑nj=1∑⌊kn⌋[gcd(j,k)=i]
令
j
′
=
j
i
j'=\dfrac{j}{i}
j′=ij,
k
′
=
k
i
k'=\dfrac{k}{i}
k′=ik,则
原
式
=
∑
i
=
1
⌊
n
⌋
i
∑
k
′
=
1
⌊
n
i
⌋
∑
j
′
=
1
⌊
n
i
2
k
′
⌋
[
gcd
(
j
′
,
k
′
)
=
1
]
原式=\sum_{i=1}^{\lfloor \sqrt{n} \rfloor}i\sum_{k'=1}^{\lfloor \frac{n}{i} \rfloor}\sum_{j'=1}^{\lfloor \frac{n}{i^2k'} \rfloor}[\gcd(j',k')=1]
原式=i=1∑⌊n⌋ik′=1∑⌊in⌋j′=1∑⌊i2k′n⌋[gcd(j′,k′)=1]
因为
∑
d
∣
n
μ
(
d
)
=
[
n
=
1
]
\sum_{d|n}\mu(d)=[n=1]
∑d∣nμ(d)=[n=1],所以
原
式
=
∑
i
=
1
⌊
n
⌋
i
∑
k
′
=
1
⌊
n
i
⌋
∑
j
′
=
1
⌊
n
i
2
k
′
⌋
∑
d
∣
gcd
(
j
′
,
k
′
)
μ
(
d
)
原式=\sum_{i=1}^{\lfloor \sqrt{n} \rfloor}i\sum_{k'=1}^{\lfloor \frac{n}{i} \rfloor}\sum_{j'=1}^{\lfloor \frac{n}{i^2k'} \rfloor}\sum_{d|\gcd(j',k')}\mu(d)
原式=i=1∑⌊n⌋ik′=1∑⌊in⌋j′=1∑⌊i2k′n⌋d∣gcd(j′,k′)∑μ(d)
改为依次枚举
d
,
j
′
,
k
′
d,j',k'
d,j′,k′,有
原
式
=
∑
i
=
1
⌊
n
⌋
i
∑
d
=
1
μ
(
d
)
∑
d
∣
j
′
⌊
n
i
⌋
∑
d
∣
k
′
⌊
n
i
2
j
′
⌋
1
=
∑
i
=
1
⌊
n
⌋
i
∑
d
=
1
μ
(
d
)
∑
d
∣
j
′
⌊
n
i
⌋
⌊
n
i
2
j
′
d
⌋
原式=\sum_{i=1}^{\lfloor \sqrt{n} \rfloor}i\sum_{d=1}\mu(d)\sum_{d|j'}^{\lfloor \frac{n}{i} \rfloor}\sum_{d|k'}^{\lfloor \frac{n}{i^2j'} \rfloor}1=\sum_{i=1}^{\lfloor \sqrt{n} \rfloor}i\sum_{d=1}\mu(d)\sum_{d|j'}^{\lfloor \frac{n}{i} \rfloor}\lfloor \frac{n}{i^2j'd} \rfloor
原式=i=1∑⌊n⌋id=1∑μ(d)d∣j′∑⌊in⌋d∣k′∑⌊i2j′n⌋1=i=1∑⌊n⌋id=1∑μ(d)d∣j′∑⌊in⌋⌊i2j′dn⌋
令
a
=
j
′
d
a=\dfrac{j'}{d}
a=dj′,则有
原
式
=
∑
i
=
1
⌊
n
⌋
i
∑
d
=
1
μ
(
d
)
∑
a
=
1
⌊
n
d
i
⌋
⌊
n
a
d
2
i
2
⌋
原式=\sum_{i=1}^{\lfloor \sqrt{n} \rfloor}i\sum_{d=1}\mu(d)\sum_{a=1}^{\lfloor \frac{n}{di} \rfloor}\lfloor \frac{n}{ad^2i^2} \rfloor
原式=i=1∑⌊n⌋id=1∑μ(d)a=1∑⌊din⌋⌊ad2i2n⌋
令
T
=
d
i
T=di
T=di,并改为依次枚举
i
,
T
i,T
i,T,则
原
式
=
∑
i
=
1
⌊
n
⌋
i
∑
i
∣
T
μ
(
T
i
)
∑
a
=
1
⌊
n
T
⌋
⌊
n
T
2
a
⌋
原式=\sum_{i=1}^{\lfloor \sqrt{n} \rfloor}i\sum_{i|T}\mu(\frac{T}{i})\sum_{a=1}^{\lfloor \frac{n}{T} \rfloor}\lfloor \frac{n}{T^2a} \rfloor
原式=i=1∑⌊n⌋ii∣T∑μ(iT)a=1∑⌊Tn⌋⌊T2an⌋
改变
i
,
T
i,T
i,T的枚举顺序,则
原
式
=
∑
T
=
1
∑
i
∣
T
μ
(
T
i
)
i
∑
a
=
1
⌊
n
T
⌋
⌊
n
T
2
a
⌋
原式=\sum_{T=1}\sum_{i|T}\mu(\frac{T}{i})i\sum_{a=1}^{\lfloor \frac{n}{T} \rfloor}\lfloor \frac{n}{T^2a} \rfloor
原式=T=1∑i∣T∑μ(iT)ia=1∑⌊Tn⌋⌊T2an⌋
因为
∑
d
∣
n
μ
(
n
d
)
d
=
ϕ
(
n
)
\sum_{d|n}\mu(\frac{n}{d})d=\phi(n)
∑d∣nμ(dn)d=ϕ(n),所以
原
式
=
∑
T
=
1
ϕ
(
T
)
∑
a
=
1
⌊
n
T
⌋
⌊
n
T
2
a
⌋
原式=\sum_{T=1}\phi(T)\sum_{a=1}^{\lfloor \frac{n}{T} \rfloor}\lfloor \frac{n}{T^2a} \rfloor
原式=T=1∑ϕ(T)a=1∑⌊Tn⌋⌊T2an⌋
因为当
⌊
n
T
2
a
⌋
≥
1
\lfloor \frac{n}{T^2a} \rfloor \geq 1
⌊T2an⌋≥1时
a
≤
⌊
n
T
2
⌋
a \leq \lfloor \frac{n}{T^2} \rfloor
a≤⌊T2n⌋,且
⌊
a
b
c
⌋
=
⌊
⌊
a
b
⌋
c
⌋
\lfloor \frac{a}{bc} \rfloor=\lfloor \frac{\lfloor \frac{a}{b} \rfloor}{c} \rfloor
⌊bca⌋=⌊c⌊ba⌋⌋,所以
原
式
=
∑
T
=
1
ϕ
(
T
)
∑
a
=
1
⌊
n
T
2
⌋
⌊
n
T
2
a
⌋
=
∑
T
=
1
ϕ
(
T
)
∑
a
=
1
⌊
n
T
2
⌋
⌊
⌊
n
T
2
⌋
a
⌋
原式=\sum_{T=1}\phi(T)\sum_{a=1}^{\lfloor \frac{n}{T^2} \rfloor}\lfloor \frac{n}{T^2a} \rfloor=\sum_{T=1}\phi(T)\sum_{a=1}^{\lfloor \frac{n}{T^2} \rfloor}\lfloor \frac{\lfloor \frac{n}{T^2} \rfloor}{a} \rfloor
原式=T=1∑ϕ(T)a=1∑⌊T2n⌋⌊T2an⌋=T=1∑ϕ(T)a=1∑⌊T2n⌋⌊a⌊T2n⌋⌋
因为当
⌊
n
T
2
⌋
≥
1
\lfloor \frac{n}{T^2} \rfloor \geq 1
⌊T2n⌋≥1时
T
≤
⌊
n
⌋
T \leq \lfloor \sqrt{n} \rfloor
T≤⌊n⌋,所以
原
式
=
∑
T
=
1
⌊
n
⌋
ϕ
(
T
)
∑
a
=
1
⌊
n
T
2
⌋
⌊
⌊
n
T
2
⌋
a
⌋
原式=\sum_{T=1}^{\lfloor \sqrt{n} \rfloor}\phi(T)\sum_{a=1}^{\lfloor \frac{n}{T^2} \rfloor}\lfloor \frac{\lfloor \frac{n}{T^2} \rfloor}{a} \rfloor
原式=T=1∑⌊n⌋ϕ(T)a=1∑⌊T2n⌋⌊a⌊T2n⌋⌋
我们发现,现在的式子可以被拆分为
ϕ
(
T
)
\phi(T)
ϕ(T)和
∑
a
=
1
⌊
n
T
2
⌋
⌊
⌊
n
T
2
⌋
a
⌋
\sum_{a=1}^{\lfloor \frac{n}{T^2} \rfloor}\lfloor \frac{\lfloor \frac{n}{T^2} \rfloor}{a} \rfloor
∑a=1⌊T2n⌋⌊a⌊T2n⌋⌋两部分计算。
计算 ϕ ( T ) \phi(T) ϕ(T)
我们发现我们要算出 1 1 1到 ⌊ n ⌋ \lfloor \sqrt{n} \rfloor ⌊n⌋的所有整数的 ϕ \phi ϕ函数的值。注意到对于正整数 n n n和素数 p p p,有 ϕ ( p ) = p − 1 \phi(p)=p-1 ϕ(p)=p−1,且当 p ∤ n p \not| \space n p∣ n时 ϕ ( n p ) = ϕ ( n ) ϕ ( p ) = ( p − 1 ) ϕ ( n ) \phi(np) = \phi(n) \phi(p) =(p-1) \phi(n) ϕ(np)=ϕ(n)ϕ(p)=(p−1)ϕ(n)、当 p ∣ n p|n p∣n时 ϕ ( n p ) = p ϕ ( n ) \phi(np)=p \phi(n) ϕ(np)=pϕ(n),于是我们考虑在一个线性筛法的基础上求出所有 ϕ \phi ϕ函数的值。我们在添加新素数时更新素数的函数值,并在筛数时根据情况讨论被筛数的函数值,这样就可以得出 1 1 1到 ⌊ n ⌋ \lfloor \sqrt{n} \rfloor ⌊n⌋的所有整数的 ϕ \phi ϕ函数的值了。
计算 ∑ a = 1 ⌊ n T 2 ⌋ ⌊ ⌊ n T 2 ⌋ a ⌋ \sum_{a=1}^{\lfloor \frac{n}{T^2} \rfloor}\lfloor \frac{\lfloor \frac{n}{T^2} \rfloor}{a} \rfloor ∑a=1⌊T2n⌋⌊a⌊T2n⌋⌋
可以发现,对于
⌊
⌊
n
T
2
⌋
a
⌋
\lfloor \frac{\lfloor \frac{n}{T^2} \rfloor}{a} \rfloor
⌊a⌊T2n⌋⌋,当式子中
n
,
T
n,T
n,T一定、
a
a
a逐渐增大时,式子的值可以被划分成一段段值相等的区间,且当
a
a
a增大到一定大小时,这种区间的大小会变得很可观。于是我们考虑从这个方向优化计算。我们考虑计算出每个区间的左右端点
l
,
r
l,r
l,r,并用一个变量累加每个区间里的总和以求出
∑
a
=
1
⌊
n
T
2
⌋
⌊
⌊
n
T
2
⌋
a
⌋
\sum_{a=1}^{\lfloor \frac{n}{T^2} \rfloor}\lfloor \frac{\lfloor \frac{n}{T^2} \rfloor}{a} \rfloor
∑a=1⌊T2n⌋⌊a⌊T2n⌋⌋。可以发现,
r
=
⌊
n
⌊
n
l
⌋
⌋
=
⌊
n
区
间
内
数
字
的
值
⌋
r=\lfloor \frac{n}{\lfloor \frac{n}{l} \rfloor} \rfloor=\lfloor \frac{n}{区间内数字的值} \rfloor
r=⌊⌊ln⌋n⌋=⌊区间内数字的值n⌋,且
下
一
个
区
间
的
左
端
点
=
当
前
区
间
的
右
端
点
+
1
下一个区间的左端点=当前区间的右端点+1
下一个区间的左端点=当前区间的右端点+1,这样我们就能快速计算出每个区间的左右端点了。
此外,我们发现对于
⌊
n
T
2
⌋
\lfloor \frac{n}{T^2} \rfloor
⌊T2n⌋(以及
∑
a
=
1
⌊
n
T
2
⌋
⌊
⌊
n
T
2
⌋
a
⌋
\sum_{a=1}^{\lfloor \frac{n}{T^2} \rfloor}\lfloor \frac{\lfloor \frac{n}{T^2} \rfloor}{a} \rfloor
∑a=1⌊T2n⌋⌊a⌊T2n⌋⌋),当
n
n
n一定、
T
T
T逐渐增大时也有类似的性质,于是我们也可以用类似的方法优化。
代码
根据思路,可以写出如下代码:
#include<cstdio> //定义头文件
#include<cmath>
using ll=long long; //将ll类型定义为long long类型
bool book[316228]; //筛法用的标记数组
ll prime[27294] /*筛法得出的素数*/ ,phi[316228]={0,1} /*phi函数的值*/ ;
int main()
{
freopen("gcd.in","r",stdin); //定义文件输入输出
freopen("gcd.out","w",stdout);
ll n;
scanf("%lld",&n); //读入n
const ll sn=sqrt(n); //预处理floor(sqrt(n))
for(ll i=2;i<=sn;++i) //通过筛法计算phi函数的值
{
if(!book[i])
{
prime[++prime[0]]=i; //增加一个素数
phi[i]=i-1;
}
for(ll j=1,max_p=sn/i;j<=prime[0]&&prime[j]<=max_p;++j) //筛数
{
book[i*prime[j]]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*phi[prime[j]];
}
}
for(ll i=2;i<=sn;++i) //求phi函数的前缀和,为下面准备
{
phi[i]+=phi[i-1];
}
ll ans=0; //统计答案
for(ll l=1 /*区间左端点*/ ,val=n/(l*l) /*区间内数的值*/ ,r /*区间右端点*/ ;l<=sn&&val>0;l=r+1,val=n/(l*l)) //利用floor(n/T^2)的性质计算ans
{
r=sqrt(n/val); //计算右端点
if(r>sn)
{
r=sn;
}
ll t=0; //统计sum(floor(floor(n/T^2)/a))的值
for(ll i=1 /*区间左端点*/ ,v=val/i /*区间内数的值*/ ,j /*区间右端点*/ ;i<=val&&v>0;i=j+1,v=val/i) //利用floor(floor(n/T^2)/a)的性质计算t
{
j=val/v; //计算右端点
if(j>val)
{
j=val;
}
t+=(j-i+1)*v; //更新t
}
ans+=(phi[r]-phi[l-1])*t; //更新ans
}
printf("%lld",ans); //输出ans
return 0;
}
总结
这是一道比较好的数论题,考察了多个数论技巧。