题解 P2398 GCD SUM
题目描述:
求
\[\sum_{i=1}^n\sum_{i=1}^n \gcd(i,j)
\]
\(1 \leq n \leq 10^5\) 。
前置知识:
欧拉函数。
Solution
考虑按照套路把原式子变形,我们设 \(f(n) = \sum_{i=1}^n\sum_{i=1}^n \gcd(i,j)\) 。
\[f(n) = \sum_{i=1}^n\sum_{i=1}^n \gcd(i,j) \\
= \sum_{k=1}^n k \times \sum_{i=1}^n\sum_{i=1}^n [\gcd(i,j)=k] \\
= \sum_{k=1}^n k \times \sum_{i=1}^n\sum_{i=1}^n[\gcd(\frac{i}{k},\frac{j}{k})=1] \\
= \sum_{k=1}^n k \times\sum_{i=1}^\frac{n}{k}\sum_{j=1}^\frac{n}{k}[\gcd(i,j)=1]
\]
设
\[g(n)=\sum_{i=1}^n\sum_{j=1}^n [\gcd(i,j)=1]
\]
考虑如何求出 \(g(n)\) 。
首先,如果是 \(g(n)=\sum_{i=1}^n \sum_{j=1}^i \gcd(i,j)\) 的话,那么答案就是
\[\sum_{i=1}^n \varphi(i)
\]
但是 \(j\) 也是 \(1\to n\) ,所以我们答案要乘二。最后,因为 \((1,1)\) 被算了两次,所以要减去一次。
\[g(n)=
=(2\times \sum_{i=2}^n \varphi(i))-1
\]
设 \(s(i)=\sum_{i=1}^n \varphi(i)\) ,那么 \(g(n)=2\times s(n)+1\) 。
\[f(n) = \sum_{k=1}^n k \times g(\frac{n}{k}) \\
= \sum_{k=1}^n k \times(2\times s(\frac{n}{k}) - 1)
\]
由于本题只有一个测试数据,考虑先预处理出 \(\varphi(1) \to \varphi(n)\) ,求出 \(\varphi\) 的前缀和,然后枚举 \(n\) 的约数,累加答案。
时间复杂度 \(\mathcal{O}(n+\sqrt{n})\) 。
代码如下:
#include <cstdio>
#include <cstring>
#define int long long
const int N = 1e5 + 5;
int prime[N] ,cnt; bool isprime[N];
int phi[N] ,s[N];
inline void Prime(int n) { //线性筛求 phi
memset(isprime ,true ,sizeof(isprime));
isprime[0] = isprime[1] = false;
phi[1] = 1;
for (int i = 2;i <= n; i++) {
if (isprime[i]) {
prime[++cnt] = i;
phi[i] = i - 1;
}
for (int j = 1;j <= cnt && i * prime[j] <= n; j++) {
isprime[i * prime[j]] = false;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
for (int i = 1;i <= n; i++) s[i] = s[i - 1] + phi[i];
}
int n ,ans;
signed main() {
scanf("%lld" ,&n);
Prime(n);
for (int i = 1;i <= n; i++)
ans += i * (2 * s[n / i] - 1);
printf("%lld\n" ,ans);
return 0;
}

题解 P2398 GCD SUM
浙公网安备 33010602011771号