题目:求 $\sum_{i=1}^n\sum_{j=1}^n\gcd(i,j)$ 的值。
推式子
∑ i = 1 n ∑ j = 1 n gcd ( i , j ) 2 \sum_{i=1}^n\sum_{j=1}^n\gcd\left(i,j\right)^2 i=1∑nj=1∑ngcd(i,j)2
= ∑ i = 1 n ∑ j = 1 n ∑ k = 1 n k 2 × [ gcd ( i , j ) = = k ] =\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^nk^2\times\left[\gcd(i,j)==k\right] =i=1∑nj=1∑nk=1∑nk2×[gcd(i,j)==k]
= ∑ k = 1 n k 2 ∑ i = 1 n ∑ j = 1 n gcd ( i , j ) =\sum_{k=1}^nk^2\sum_{i=1}^n\sum_{j=1}^n\gcd(i,j) =k=1∑nk2i=1∑nj=1∑ngcd(i,j)
= ∑ k = 1 n k 2 ( 2 ∑ i = 1 ⌊ n k ⌋ φ ( i ) − 1 ) =\sum_{k=1}^nk^2\left(2\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\varphi(i)-1\right) =k=1∑nk2 2i=1∑⌊kn⌋φ(i)−1
代入杜教筛公式。
= ∑ k = 1 n k 2 ( n 2 + n − ∑ i = 2 n S ( ⌊ n i ⌋ ) ) =\sum_{k=1}^nk^2\left(n^2+n-\sum_{i=2}^n S\left(\lfloor\dfrac{n}{i}\rfloor\right)\right) =k=1∑nk2(n2+n−i=2∑nS(⌊in⌋))
实现
先用欧拉筛筛出前 K K K 个,再求。
复杂度 Θ ( K + n K ) = Θ ( n 2 3 ) \Theta\left(K+\dfrac{n}{\sqrt{K}}\right) = \Theta(n^{\frac{2}{3}}) Θ(K+Kn)=Θ(n32).
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1000000007;
unordered_map<int, int>mp;
int K = 10000;
int s[500010];
inline int S(int x) {if (x <= K)return s[x];//预处理if (mp.find(x) != mp.end())return mp[x];//记忆化int j = 0;int ans = 1ll * (x) * (x + 1) / 2;for (int i = 2; i <= x; i = j + 1) {j = x / (x / i);//数论分块ans -= (j - i + 1) * S(x / i);//个数*每个的值}return mp[x] = (ans % mod);
}
int primes[500010];
int cnt;
bool st[500010];
inline void init() {//欧拉筛求欧拉函数s[1] = 1;for (int i = 2; i <= K; i++) {if (!st[i]) {primes[cnt++] = i;s[i] = i - 1; //质数前面所有数都互质}for (int j = 0; primes[j] <= K / i; j++) {int t = primes[j] * i;st[t] = true;if (i % primes[j] == 0) {s[t] = primes[j] * s[i];break;}s[t] = s[i] * (primes[j] - 1);}}for (int i = 1; i <= K; i++)s[i] += s[i - 1], s[i] %= mod;
}
signed main() {int n;cin >> n;init();int ans = 0;for (int i = 1; i <= n; ++i)ans = (ans + ((i * i) % mod * ( (S(n / i) << 1) % mod - 1 )) % mod) % mod;//公式cout << ans;return 0;
}