Luo Gu 2257: YY the GCD
Description of the meaning of problems
- Q \ (\ sum_. 1} = {I ^ N \ sum_. 1} = {J ^ M [GCD (I, J) == P] \) , where \ (P \) are all prime numbers.
- Data range \ (N, M \. 7 Leq 10 ^ \) , there are \ (10000 \) set of test data.
Ideas:
- Mobius inversion
- Set \ (f (d) \) of \ (gcd (i, j) == d \) number: \ (F (D) = \ sum_. 1} ^ {n-I = \ sum_ = {J}. 1 m ^ [GCD (I, J) == D] \) .
- \ (F (n) \) of \ (gcd (i, j) == kn \) number, where \ (K = 1,2, ... \) .
- 有\(F(n)=\sum_{n|d}f(d)=\frac{N}{n}\frac{M}{n}\)。
\(f(n)=\sum_{n|d}\mu(\frac{d}{n})F(d)\)。
\(ans=\sum_{p\in primes}\sum_{i=1}^N\sum_{j=1}^M[gcd(i,j)==p]\).
\(=\sum_{p\in primes}f(p)\)。
\(=\sum_{p\in primes}\sum_{p|d}\mu(\frac{d}{p})F(d)\).
Enumeration \ (\ FRAC {P} = {D} T \) , there
\(=\sum_{p\in primes}\sum_{t=1}^{min\{\frac{N}{p},\frac{M}{p}\}}\mu(t)\frac{N}{tp}\frac{M}{tp}\)。
Set \ (T = TP \) , are:
\(\sum_{p\in primes}\sum_{t=1}^{min\{\frac{N}{p},\frac{M}{p}\}}\mu(t)*\frac{N}{T}\frac{M}{T}\)。
Enumerate what \ (T \) , are:
\(\sum_{T=1}^{min\{N,M\}}\frac{N}{T}\frac{M}{T}\sum_{k|T,k\in primes}\mu(\frac{T}{k})\)。
This latter may be pretreated prefix and a summing \ (O (1) \) query.
Divisible by a preceding block may be optimized to \ (O (\ n-sqrt {}) \) .
#include<bits/stdc++.h> using namespace std; const int maxn = 1e7 + 1e5; int mu[maxn], primes[maxn], cnt; long long sum[maxn], f[maxn]; bool vis[maxn]; void get_mu(int n) { mu[1] = 1; for(int i = 2; i <= n; i++) { if(!vis[i]) { primes[++cnt] = i; mu[i] = -1; } for(int j = 1; primes[j] <= n/i; j++) { vis[primes[j]*i] = 1; if(i % primes[j] == 0) break; else mu[i*primes[j]] = -mu[i]; } } for(int i = 1; i <= cnt; i++) for(int j = 1; primes[i] <= n/j; j++) f[j*primes[i]] += mu[j]; for(int i = 1; i <= n; i++) sum[i] = sum[i-1] + f[i]; } int main() { get_mu(10000000+5); int T; scanf("%d", &T); while(T--) { int n, m; long long ans = 0; scanf("%d%d", &n, &m); if(n > m) swap(n, m); for(int l = 1, r; l <= n; l = r+1) { r = min(n/(n/l), m/(m/l)); ans += 1ll*(1ll*(n/l)*1ll*(m/l) * (sum[r]-sum[l-1])); } printf("%lld\n", ans); } return 0; }