[洛谷2257]ZAP-Queries 题解

前言

这道题还是比较简单的

解法

首先将题目转化为数学语言。
题目要我们求的是:

\[\sum_{i=1}^a\sum_{j=1}^b[gcd(i,j)=d] \]

按照套路1,我们将其同时除以d转换为

\[\sum_{i=1}^{\lfloor\frac{a}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{b}{d}\rfloor}[gcd(i,j)=1] \]

按照技巧1,我们将其变换为

\[\sum_{i=1}^{\lfloor\frac{a}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{b}{d}\rfloor}\sum_{x|gcd(i,j)}\mu(x) \]

按照技巧3,我们将其变换为

\[\sum_{i=1}^{\lfloor\frac{a}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{b}{d}\rfloor}\sum_{x=1}^{\lfloor\frac{a}{d}\rfloor}\mu(x)\times[x|gcd(i,j)] \]

我们发现要满足\(d|gcd(i,j)\),我们的i,j必须是d的倍数
然后我们可以开心地去掉两个\(\sum\)

\[\sum_{x=1}^{\lfloor\frac{a}{d}\rfloor}\mu(x)\times\lfloor\frac{a}{xd}\rfloor\lfloor\frac{b}{xd}\rfloor \]

至此化简结束,我们求出\(\mu\)函数的前缀和
然后我们整除分块,解决问题

代码

#include <cstdio>
#include <algorithm>
#define ll long long
#define MAXNUM 500005

int mu[MAXNUM], is_not_prime[MAXNUM], primes[MAXNUM / 10], prime_num;
// prefix
ll qzh[MAXNUM];

int read(){
    int x = 0; int zf = 1; char ch = ' ';
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') zf = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
}

void init(){
    mu[1] = 1; is_not_prime[0] = is_not_prime[1] = 1;
    for (int i = 2; i <= MAXNUM; ++i){
        if (!is_not_prime[i]) mu[primes[++prime_num] = i] = -1;
        for (int j = 1; j <= prime_num && primes[j] * i <= MAXNUM; ++j){
            is_not_prime[i * primes[j]] = 1;
            if (!(i % primes[j])) break;
            else
                mu[primes[j] * i] = -mu[i];
        }
    }
    for (int i = 1; i <= MAXNUM; ++i)
        qzh[i] = qzh[i - 1] + mu[i];
}

int main(){
    init();
    int T = read(), n, m, d; ll ans;
    while (T--){
        n = read(), m = read(), d = read();
        n /= d, m /= d;
        if (n > m) n ^= m ^= n ^= m; ans = 0;
        for (int l = 1, r; l <= n; l = r + 1){
            r = std::min(n / (n / l), m / (m / l));
            ans += (ll)(qzh[r] - qzh[l - 1]) * (n / l) * (m / l);
        }
        printf("%lld\n", ans);
    }
    return 0;
}

P.S. 数组开的好像有点大,不要介意

posted @ 2019-06-21 21:08  LinZhengmin  阅读(239)  评论(0编辑  收藏  举报

Contact with me