题目让你求:
i=1∑nlcm(i,j)
推式子:
=i=1∑ngcd(i,n)i,n
=ni=1∑ngcd(i,n)i
=nd∣n∑i=1∑ndi[gcd(i,n)=d]
=nd∣n∑i=1∑n/di[gcd(id,n)=d]
=nd∣n∑i=1∑n/di[gcd(i,dn)=1]
=nd∣n∑i=1∑di[gcd(i,d)=1]
=nd∣n∑2dϕ(d)
到这里就直接可以预处理每个n的约数2dϕ(d)值和了。
代码不开ios加速会TLE。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| #include<bits/stdc++.h> using namespace std; #define int long long vector<int> phisieve(int n) { vector<int> primes, phi(n + 1); vector<bool> vis(n + 1, 0); phi[1] = 1, phi[0] = 0; vis[0] = vis[1] = 1; for (int i = 2; i <= n; i++) { if (!vis[i]) { phi[i] = i - 1; primes.push_back(i); } for (int j = 0; j < primes.size() && i * primes[j] <= n; j++) { vis[i * primes[j]] = 1; if (i % primes[j]) { phi[i * primes[j]] = phi[i] * (primes[j] - 1); } else { phi[i * primes[j]] = phi[i] * primes[j]; break; } } } return phi; } vector<int> phi; vector<int> v(1e6 + 10, 0); void solve() { int n; cin >> n; cout << n * v[n] << '\n'; } signed main() { ios::sync_with_stdio(); cin.tie(0); cout.tie(0); phi = phisieve(1e6 + 10); for (int i = 1; i <= 1e6; i++) { for (int j = 1; i * j <= 1e6; j++) { v[i * j] += (i == 1 ? 1 : i * phi[i] / 2); } } int T; cin >> T; while (T--) { solve(); } return 0; }
|