【LG2257】YY的GCD
阿新 • • 發佈:2018-12-26
【LG2257】YY的GCD
題面
題解
題目大意:
給定\(n,m\)求\(\Sigma_{i=1}^{n}\Sigma_{j=1}^{m}[gcd(i,j)為質數]\)。
我們設\(f(x)=[x為質數]\),需要找到一個\(g\)使得\(f=1*g\),那麼\(g=\mu*f\)
\(g(x)=\Sigma_{d|x}\mu(\frac{x}{d})*f(d)=\Sigma_{p|x}\mu(\frac{x}{p})\)
這樣的話,我們要求的就是
\(\Sigma_{i=1}^{n}\Sigma_{j=1}^{m}\Sigma_{d|i,d|j}g(d)\)
\(=\Sigma_{d=1}^{min(n,m)}g(d)\Sigma_{i=1}^{n}\Sigma_{j=1}^{m}[d|i][d|j]\)
\(=\Sigma_{d=1}^{min(n,m)}g(d)\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor\)
可以用數論分塊求出
程式碼
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; inline int gi() { register int data = 0, w = 1; register char ch = 0; while (!isdigit(ch) && ch != '-') ch = getchar(); if (ch == '-') w = -1, ch = getchar(); while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); return w * data; } typedef long long ll; const int MAX_N = 1e7 + 5; const int MAX = 1e7; bool is_prime[MAX_N]; int prime[MAX_N], num, mu[MAX_N], s[MAX_N], f[MAX_N]; void sieve() { for (int i = 1; i <= MAX; i++) is_prime[i] = 1; is_prime[1] = 0, mu[1] = 1; for (int i = 2; i <= MAX; i++) { if (is_prime[i]) prime[++num] = i, mu[i] = -1; for (int j = 1; j <= num && i * prime[j] <= MAX; j++) { is_prime[i * prime[j]] = 0; if (i % prime[j] == 0) break; mu[i * prime[j]] = -mu[i]; } } for (int i = 1; i <= num; i++) for (int j = 1; prime[i] * j <= MAX; j++) f[j * prime[i]] += mu[j]; for (int i = 1; i <= MAX; i++) s[i] = s[i - 1] + f[i]; } ll solve(int a, int b) { ll ans = 0; if (a > b) swap(a, b); for (int l = 1, r = 0; l <= a; l = r + 1) { r = min(a / (a / l), b / (b / l)); ans += 1ll * (s[r] - s[l - 1]) * (a / l) * (b / l); } return ans; } int main () { #ifndef ONLINE_JUDGE freopen("cpp.in", "r", stdin); #endif sieve(); int T = gi(), N, M; while (T--) { N = gi(), M = gi(); printf("%lld\n", solve(N, M)); } return 0; }