洛谷2257 YY的GCD 复习

众所周知,这题是个人就会。

$$ \text{钦定}N\le M \\ \sum_{1\le i\le N}{\sum_{1\le j\le M}{\left[ \mathrm{gcd}\left( i,j \right) =p \right]}} \\ \sum_p{\sum_{1\le pi\le N}{\sum_{1\le pj\le M}{\left[ \mathrm{gcd}\left( pi,pj \right) =p \right]}}} \\ \sum_p{\sum_{1\le i\le \lfloor \frac{N}{p} \rfloor}{\sum_{1\le j\le \lfloor \frac{M}{p} \rfloor}{\left[ \mathrm{gcd}\left( i,j \right) =1 \right]}}} \\ \sum_p{\sum_{1\le i\le \lfloor \frac{N}{p} \rfloor}{\sum_{1\le j\le \lfloor \frac{M}{p} \rfloor}{\sum_{k|gcd\left( i,j \right)}{\mu \left( k \right)}}}} \\ \sum_p{\sum_{1\le k\le \lfloor \frac{N}{p} \rfloor}{\sum_{1\le ik\le \lfloor \frac{N}{p} \rfloor}{\sum_{1\le jk\le \lfloor \frac{M}{p} \rfloor}{\sum_{k|gcd\left( ik,jk \right)}{\mu \left( k \right)}}}}} \\ \sum_p{\sum_{1\le k\le \lfloor \frac{N}{p} \rfloor}{\sum_{1\le i\le \lfloor \frac{N}{kp} \rfloor}{\sum_{1\le j\le \lfloor \frac{M}{kp} \rfloor}{\mu \left( k \right)}}}} \\ \sum_{1\le p\le N,p\,\,is\,\,prime}{\sum_{1\le k\le \lfloor \frac{N}{p} \rfloor}{\mu \left( k \right) \lfloor \frac{N}{kp} \rfloor \lfloor \frac{M}{kp} \rfloor}} \\ T=kp \\ T\le N \\ \sum_{1\le T\le N}{\sum_{p|T\left( T\text{的所有质因数} \right)}{\lfloor \frac{N}{T} \rfloor \lfloor \frac{M}{T} \rfloor \mu \left( \frac{T}{p} \right)}} \\ =\sum_{1\le T\le N}{\lfloor \frac{N}{T} \rfloor \lfloor \frac{M}{T} \rfloor \sum_{p|T,\left( T\text{的所有质因数} \right)}{\mu \left( \frac{T}{p} \right)}} $$
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using int_t = long long int;
using std::cin;
using std::cout;
using std::endl;

const int_t LARGE = 2e7;

int f[LARGE + 1];
int fSum[LARGE + 1];
int mu[LARGE + 1];
int factor[LARGE + 1];
bool isPrime[LARGE + 1];

std::vector<int> primes;

int_t query(int_t n, int_t m) {
    if (n > m)
        std::swap(n, m);
#ifdef DEBUG
    cout << "process " << n << " " << m << endl;
#endif
    int_t i = 1;
    int_t result = 0;
    while (i <= n) {
        int_t next = std::min(n / (n / i), m / (m / i));
        result += (n / i) * (m / i) * (fSum[next] - fSum[i - 1]);
        i = next + 1;
    }
    return result;
}

int main() {
    std::ios::sync_with_stdio(false);
    memset(isPrime, 1, sizeof(isPrime));
    isPrime[1] = false;
    for (int_t i = 2; i <= LARGE; i++) {
        if (isPrime[i]) {
            primes.push_back(i);
            for (int_t j = i * i; j <= LARGE; j += i) {
                isPrime[j] = false;
                if (factor[j] == 0)
                    factor[j] = i;
            }
            factor[i] = i;
        }
    }
    mu[1] = 1;
    for (int_t i = 2; i <= LARGE; i++) {
        int_t factor = ::factor[i];
        if (i / factor % factor == 0) {
            mu[i] = 0;
        } else {
            mu[i] = mu[i / factor] * -1;
        }
    }
    for (auto prime : primes) {
        for (int_t j = 1; j * prime <= LARGE; j++) {
            f[j * prime] += mu[j];
        }
    }
#ifdef DEBUG
    for (int_t i = 2; i <= 100; i++) {
        cout << i << ": factor=" << factor[i] << " isPrime=" << isPrime[i]
             << " mu=" << mu[i] << " f=" << f[i] << endl;
    }

#endif
    for (int_t i = 2; i <= LARGE; i++)
        fSum[i] = fSum[i - 1] + f[i];
    int T;
    scanf("%d", &T);
    while (T--) {
        int n, m;
        scanf("%d%d", &n, &m);
        int_t result = query(n, m);
        printf("%lld\n", result);
    }
    return 0;
}<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1">​</span>

 

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理