【GDSOI 2016】第一题 互补约数
Description
求 F ( n ) = ∑ i = 1 n ∑ d ∣ i gcd ( d , i d ) F(n)=\sum_{i=1}^n\sum_{d|i}\gcd(d,\frac{i}{d}) F(n)=∑i=1n∑d∣igcd(d,di)
Solution
欧拉反演:
n
=
∑
d
∣
n
φ
(
d
)
n=\sum_{d|n}\varphi(d)
n=d∣n∑φ(d)
对
F
(
n
)
F(n)
F(n)中的
g
c
d
(
d
,
i
d
)
gcd(d,\frac{i}{d})
gcd(d,di)应用上式,得
F
(
n
)
=
∑
i
=
1
n
∑
d
∣
i
∑
j
∣
gcd
(
d
,
i
d
)
φ
(
j
)
F(n)=\sum_{i=1}^n\sum_{d|i}\sum_{j|\gcd(d,\frac{i}{d})}\varphi(j)
F(n)=i=1∑nd∣i∑j∣gcd(d,di)∑φ(j)
拆一下
gcd
(
d
,
i
d
)
\gcd(d,\frac{i}{d})
gcd(d,di),得
F
(
n
)
=
∑
i
=
1
n
∑
d
∣
i
∑
j
∣
d
且
j
∣
i
d
φ
(
j
)
F(n)=\sum_{i=1}^n\sum_{d|i}\sum_{j|d且j|\frac{i}{d}}\varphi(j)
F(n)=i=1∑nd∣i∑j∣d且j∣di∑φ(j)
改为枚举j,得
F
(
n
)
=
∑
j
=
1
n
φ
(
j
)
∑
d
=
1
⌊
n
j
2
⌋
⌊
⌊
n
j
2
⌋
d
⌋
F(n)=\sum_{j=1}^{\sqrt{n}}\varphi(j)\sum_{d=1}^{\lfloor\frac{n}{j^2}\rfloor}\lfloor\frac{\lfloor\frac{n}{j^2}\rfloor}{d}\rfloor
F(n)=j=1∑nφ(j)d=1∑⌊j2n⌋⌊d⌊j2n⌋⌋
数论分块可以做了。复杂度
O
(
n
3
4
)
O(n^\frac{3}{4})
O(n43)
记得开龙龙
Code
#include <cstdio>
#include <iostream>
#define int long long
using namespace std;
int n, ans, phi[10000010], cnt, sum;
int vis[10000010], p[1000010];
int read() {
int res = 0, flag = 1;
char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar())
if(ch == '-') flag = -1;
for(; ch >= '0' && ch <= '9'; res = res * 10 + ch - '0', ch = getchar());
return res * flag;
}
signed main() {
n = read();
phi[1] = 1;
for(int i = 2; i * i <= n; ++i) {
if(!vis[i]) {
p[++cnt] = i;
phi[i] = i - 1;
}
for(int j = 1; j <= cnt && (p[j] * i) * (p[j] * i) <= n; ++j) {
vis[i * p[j]] = 1;
if(i % p[j] == 0) {
phi[i * p[j]] = phi[i] * p[j];
break;
}
phi[i * p[j]] = phi[i] * phi[p[j]];
}
}
for(int i = 1; i * i <= n; ++i) {
sum = 0;
int m = n / (i * i);
for(int l = 1, r; l <= m; l = r + 1) {
r = m / (m / l);
sum += (r - l + 1) * (m / l);
}
ans += phi[i] * sum;
}
printf("%lld\n",ans);
return 0;
}