1. 程式人生 > >【LG2257】YY的GCD

【LG2257】YY的GCD

【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; 
}