码迷,mamicode.com
首页 > 其他好文 > 详细

YY的GCD

时间:2018-11-17 13:16:05      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:==   std   prim   sum   class   sqrt   ++i   scanf   数组   

Description

给出 \(T\)\(n, m\),求 \(1 \leq i \leq n, 1 \leq j \leq m\)\(gcd(i, j)\) 为质数的 \((i, j)\) 有多少对。

Solution

假设 \(n<m\)

\[\sum\limits_{isprime(p)}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[gcd(i,j)=p]\\sum\limits_{isprime(p)}\sum\limits_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{p}\rfloor}[gcd(i,j)=1]\\sum\limits_{isprime(p)}\sum\limits_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{p}\rfloor}\sum\limits_{d|gcd(i,j)}\mu(d)\\sum\limits_{isprime(p)}\sum\limits_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{p}\rfloor}\sum\limits_{d|i\wedge d|j}\mu(d)\\sum\limits_{isprime(p)}\sum\limits_{d=1}^{\lfloor\frac{n}{p}\rfloor}\mu(d){\left\lfloor\frac{n}{pd}\right\rfloor}{\left\lfloor\frac{m}{pd}\right\rfloor}\]

\(k=pd\)

\[\sum\limits_{k=1}^{n}\sum\limits_{isprime(p)\wedge p|k}\mu(\frac{k}{p}){\left\lfloor\frac{n}{k}\right\rfloor}{\left\lfloor\frac{m}{k}\right\rfloor}\\sum\limits_{k=1}^{n}f(k){\left\lfloor\frac{n}{k}\right\rfloor}{\left\lfloor\frac{m}{k}\right\rfloor}\]

线性筛出 \(f\) 数组,然后整除分块,复杂度 \(O(n+T(\sqrt n+\sqrt m))\)

Code

#include <cstdio>

const int N = 10000005;
int n, m, T, tot, np[N], p[N], mu[N], sum[N];

int min(int x, int y) {
    return x < y ? x : y;
}
void getmu(int n) {
    np[1] = mu[1] = 1;
    for (int i = 2; i <= n; ++i) {
        if (!np[i]) p[++tot] = i, mu[i] = -1;
        for (int j = 1; j <= tot && p[j] * i <= n; ++j) {
            np[p[j]*i] = 1;
            if (i % p[j] == 0) {
                mu[p[j]*i] = 0;
                break;
            } mu[p[j]*i] = -mu[i];
        }
    }
}
void prev(int n) {
    for (int i = 1; i <= tot; ++i)
        for (int j = p[i]; j <= n; j += p[i])
            sum[j] += mu[j/p[i]];
    for (int i = 2; i <= n; ++i) sum[i] += sum[i-1];
}

int main() {
    scanf("%d", &T), getmu(1e7), prev(1e7);
    while (T--) {
        scanf("%d%d", &n, &m);
        if (n > m) n ^= m, m ^= n, n ^= m;
        long long ans = 0;
        for (int l = 1, r; l <= n; l = r + 1) {
            r = min(n / (n / l), m / (m / l));
            ans += 1LL * (sum[r] - sum[l-1]) * (n / l) * (m / l);
        }
        printf("%lld\n", ans);
    }
    return 0;
}

YY的GCD

标签:==   std   prim   sum   class   sqrt   ++i   scanf   数组   

原文地址:https://www.cnblogs.com/fly-in-milkyway/p/9973467.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!