传送门
题意:求出
\(\sum\limits_{i=1}^{n}\sum\limits_{j=i+1}^{n}\gcd(i,j)\)
原式
\(=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i - 1}\gcd(i,j)\)
\(=\sum\limits_{d=1}^n\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i - 1}[gcd(i,j) = d]\)
\(=\sum\limits_{d=1}^n\sum\limits_{i=1}^{\frac{n}{d}}\sum\limits_{j=1}^{i-1}d\times [gcd(i,j) = 1]\)
\(=\sum\limits_{d=1}^nd\times \sum\limits_{i=1}^{\frac{n}{d}}\varphi(i)\)
令:\(phi(x) =\sum\limits_{i=1}^x\varphi(i)\)。
原式:
\(=\sum\limits_{d=1}^nd\times phi(\frac{n}{d})\)
注意:这一题中 \(\varphi(1) = 0\),因为求和时是从 1 至 i - 1。
这里可以用整除分块来做,时间复杂度:\(O(n+T\sqrt n)\)。
AcCode:
``````cpp
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e6, inf = 1e9, P = inf + 7;
int v[N + 1], cnt[N + 1];
ll phi[N + 1];
vector<int> ve;
void init() {
phi[1] = 0;
for (int i = 2; i <= N; i++) {
if (!v[i]) {
v[i] = i;
phi[i] = i - 1;
ve.push_back(i);
}
for (auto j : ve) {
if (j > i || j > N / i) break;
v[i * j] = j;
phi[i * j] = phi[i] * (i % j ? j - 1 : j);
}
}
for (int i = 1; i <= N; i++)
phi[i] += phi[i - 1];
}
int main() {
init();
int T = 1;
// scanf("%d", &T);
while (T--) {
int n;
scanf("%d", &n);
if (n == 0)
break;
ll ans = 0;
for (int d = 1; d <= n; d++) {
int k = n / (n / d);
ans += phi[n / d] * (d + k) * (k - d + 1) / 2;
d = k;
}
printf("%lld\n", ans);
}
return 0;
}
标签:phi,gcd,limits,int,题解,sum,P1390,varphi,公约数
From: https://www.cnblogs.com/Vancezyx/p/17051925.html