【题目链接】
【题目考点】
1. 数论:欧拉函数
欧拉函数 ϕ ( x ) \phi(x) ϕ(x)表示小于等于 x x x的与 x x x互质的数的个数。
欧拉函数具有如下性质:
n
=
∑
d
∣
n
ϕ
(
d
)
n=\sum_{d|n}\phi(d)
n=∑d∣nϕ(d),即正整数n等于n的所有约数的欧拉函数值的加和。
2. 线性筛:求1到n的欧拉函数值
已知:对于质数
p
p
p
如果
p
∣
x
p \mid x
p∣x,则
ϕ
(
p
x
)
=
p
ϕ
(
x
)
\phi(px)=p\phi(x)
ϕ(px)=pϕ(x)
如果
p
∤
x
p\nmid x
p∤x,则
ϕ
(
p
x
)
=
(
p
−
1
)
ϕ
(
x
)
\phi(px)=(p-1)\phi(x)
ϕ(px)=(p−1)ϕ(x)
在线性筛求质数时,i是当前访问的数值,prime[j]是当前遍历到的质数,phi[i]表示欧拉函数
ϕ
(
i
)
\phi(i)
ϕ(i)。
当确定i*prime[j]的最小质因数为prime[j]时,判断
如果i%prime[j] == 0,则phi[i*prime[j]] = prime[j]*phi[i]
否则如果i%prime[j] != 0,则phi[i*prime[j]] = (prime[j]-1)*phi[i]
递推可以求出1到n的欧拉函数。
【解题思路】
本题求:
∑
i
=
1
n
∑
j
=
1
n
gcd
(
i
,
j
)
\sum_{i=1}^n \sum_{j=1}^n \gcd(i, j)
i=1∑nj=1∑ngcd(i,j)
根据欧拉函数的性质
n
=
∑
d
∣
n
ϕ
(
d
)
n=\sum\limits_{d|n}\phi(d)
n=d∣n∑ϕ(d),有:
g
c
d
(
i
,
j
)
=
∑
d
∣
g
c
d
(
i
,
j
)
ϕ
(
d
)
gcd(i,j)=\sum\limits_{d|gcd(i,j)}\phi(d)
gcd(i,j)=d∣gcd(i,j)∑ϕ(d)
已知:
d
∣
a
,
d
∣
b
d|a, d|b
d∣a,d∣b等价于
d
∣
g
c
d
(
a
,
b
)
d|gcd(a,b)
d∣gcd(a,b),即公约数整除最大公约数。
那么:
g
c
d
(
i
,
j
)
=
∑
d
∣
i
,
d
∣
j
ϕ
(
d
)
gcd(i,j)=\sum\limits_{d|i, d|j}\phi(d)
gcd(i,j)=d∣i,d∣j∑ϕ(d)
∑
i
=
1
n
∑
j
=
1
n
gcd
(
i
,
j
)
=
∑
i
=
1
n
∑
j
=
1
n
∑
d
∣
i
,
d
∣
j
ϕ
(
d
)
\sum\limits_{i=1}^n \sum\limits_{j=1}^n \gcd(i, j)=\sum\limits_{i=1}^n \sum\limits_{j=1}^n\sum\limits_{d|i, d|j}\phi(d)
i=1∑nj=1∑ngcd(i,j)=i=1∑nj=1∑nd∣i,d∣j∑ϕ(d)
即:
i
、
j
i、j
i、j分别枚举区间
[
1
,
n
]
[1,n]
[1,n]的值,如果
d
d
d是
i
i
i与
j
j
j的公约数,那么对结果贡献为
ϕ
(
d
)
\phi(d)
ϕ(d)
由于
i
、
j
i、j
i、j能取到的最大值为
n
n
n,所以
i
、
j
i、j
i、j的公约数小于等于
n
n
n,因此
i
、
j
i、j
i、j的公约数
d
d
d的取值范围为
[
1
,
n
]
[1,n]
[1,n]。
因此可以在
[
1
,
n
]
[1,n]
[1,n]范围内枚举
d
d
d的值,对于每个
d
d
d的取值考察其对结果的贡献。
只有当
d
∣
i
,
d
∣
j
d|i, d|j
d∣i,d∣j,即
i
i
i是
d
d
d的倍数且
j
j
j是
d
d
d的倍数时,才有贡献
ϕ
(
d
)
\phi(d)
ϕ(d)。
i
i
i的取值范围为
[
1
,
n
]
[1, n]
[1,n],其中
d
d
d的倍数有
d
,
2
d
,
.
.
.
,
⌊
n
d
⌋
d
d, 2d, ..., \lfloor \frac{n}{d} \rfloor d
d,2d,...,⌊dn⌋d,共有
⌊
n
d
⌋
\lfloor \frac{n}{d} \rfloor
⌊dn⌋ 个
d
d
d的倍数。
j
j
j的取值范围为
[
1
,
n
]
[1, n]
[1,n],同样其中共有
⌊
n
d
⌋
\lfloor \frac{n}{d} \rfloor
⌊dn⌋ 个
d
d
d的倍数。
i
i
i取
d
d
d的倍数的情况有
⌊
n
d
⌋
\lfloor \frac{n}{d} \rfloor
⌊dn⌋种,
j
j
j取
d
d
d的倍数的情况有
⌊
n
d
⌋
\lfloor \frac{n}{d} \rfloor
⌊dn⌋种,根据乘法原理,
i
、
j
i、j
i、j同时取
d
d
d的倍数的情况有
⌊
n
d
⌋
2
\lfloor \frac{n}{d} \rfloor^2
⌊dn⌋2种。
因此,当
i
、
j
i、j
i、j的公约数为
d
d
d时,对结果的贡献为
⌊
n
d
⌋
2
ϕ
(
d
)
\lfloor \frac{n}{d} \rfloor^2\phi(d)
⌊dn⌋2ϕ(d)
因此:
∑
i
=
1
n
∑
j
=
1
n
gcd
(
i
,
j
)
=
∑
d
=
1
n
⌊
n
d
⌋
2
ϕ
(
d
)
\sum_{i=1}^n \sum_{j=1}^n \gcd(i, j)=\sum\limits_{d=1}^n\lfloor \frac{n}{d} \rfloor^2\phi(d)
i=1∑nj=1∑ngcd(i,j)=d=1∑n⌊dn⌋2ϕ(d)
在 [ 1 , n ] [1,n] [1,n]范围内枚举 d d d的值,将 ⌊ n d ⌋ 2 ϕ ( d ) \lfloor \frac{n}{d} \rfloor^2\phi(d) ⌊dn⌋2ϕ(d)加和即为结果。
该计算过程需要用到1到n的欧拉函数值,可以使用线性筛预处理求出
ϕ
(
1
)
∼
ϕ
(
n
)
\phi(1)\sim \phi(n)
ϕ(1)∼ϕ(n)的值。
该算法时间复杂度为
O
(
n
)
O(n)
O(n)。
【题解代码】
#include <bits/stdc++.h>
using namespace std;
#define N 100005
bool isPrime[N];
int prime[N], pn, phi[N];
long long n, ans;
void eulerSeive(int n)
{
memset(isPrime, 1, sizeof(isPrime));
phi[1] = 1;
for(int i = 2; i <= n; ++i)
{
if(isPrime[i])
{
prime[++pn] = i;
phi[i] = i-1;
}
for(int j = 1; j <= pn && i*prime[j] <= n; ++j)
{
isPrime[i*prime[j]] = false;
if(i%prime[j] == 0)
{
phi[i*prime[j]] = prime[j]*phi[i];
break;
}
else
phi[i*prime[j]] = (prime[j]-1)*phi[i];
}
}
}
int main()
{
cin >> n;
eulerSeive(n);
for(int d = 1; d <= n; ++d)
ans += (n/d)*(n/d)*phi[d];
cout << ans;
return 0;
}

1028

被折叠的 条评论
为什么被折叠?



