• YY的GCD


    洛谷有, 卡快读

    题面

    神犇 YY 虐完数论后给傻× kAc 出了一题

    给定 N, M 且 gcd(x,y) 为质数的 (x, y)(x,y) 有多少对。

    输入格式

    第一行一个整数 T 表述数据组数。

    接下来 T 行,每行两个正整数,N, M。

    输出格式

    T 行,每行一个整数表示第 i 组数据的结果。

    输入输出样例

    输入1

    2
    10 10
    100 100
    

    输出1

    30
    2791
    
    $ T = 10^4,N, M leq 10^7$ 
    

    题解

    设 F(n) 表示 gcd(x, y) == k的倍数 的(x, y)的对数, f(n) 表示 gcd(x, y) == k 的(x, y)的对数

    $F(n) = sum_{n | d} f(d) = left lfloor frac {n} {k} ight floor imes left lfloor frac {m} {k} ight floor $

    由莫比乌斯反演得, (f(n) = sum_{n | d} mu (frac {d} {n}) F(d))

    变换区间, 左区间向上、右区间向下取整, 直接求 gcd(x / k, y / k) == 1, 即f(1) 为解

    (f(1) = sum_{d = 1}^{left lfloor frac {min(n, m)} {k} ight floor} mu (d) imes left lfloor frac {n} {k} ight floor imes left lfloor frac {m} {k} ight floor)

    (ans = sum_{p in prime} sum_{p | d} mu (frac {d} {p}) imes F(d))

    设 d = k * p

    (ans = sum_{p in prime} sum_{k = 1}^{frac {min(n, m)} {p} } mu (k) imes F(kp))

    (ans = sum_{d = 1}^{min(n, m)} F(d) imes sum_{p in d_{prime}} mu (d))

    带入 F(n) 分块可求, (sum_{p in d_{prime}} mu (d)) 预处理前缀和

    //快读省略
    const int N = 1e7 + 5;
    
    int n, m = 1e7, _, k;
    int prime[N], miu[N], cnt, a, b;
    long long sum[N], x;
    bool v[N];
    
    void init() {
        miu[1] = 1;
        for (int i = 2; i <= m; ++i) {
            if (!v[i]) prime[++cnt] = i, miu[i] = -1;
            for (int j = 1; j <= cnt && prime[j] <= m / i; ++j) {
                v[i * prime[j]] = 1;
                if (i % prime[j] == 0) break;
                miu[prime[j] * i] = -miu[i];
            }
        }
        for (int i = 1; i <= cnt; ++i)
            for (int j = 1; j <= m / prime[i]; ++j) sum[prime[i] * j] += miu[j];
    
        for (int i = 2; i <= m; ++i) sum[i] += sum[i - 1];
    }
    
    int main() {
        init();
        for (scan(_); _; --_) {
            scan(a); scan(b); x = 0;
            if (a > b) swap(a, b);
            for (int l = 1, r; l <= a; l = r + 1) {
                r = min(b / (b / l), a / (a / l));
                x += (sum[r] - sum[l - 1]) * (b / l) * (a / l);
            }
            print(x); putchar('
    ');
        }
        return 0;
    }
    

    即 ans = sum_{}

  • 相关阅读:
    C/C++内存管理 笔记
    RAII惯用法:C++资源管理的利器
    JS、Flash 实现复制功能 (浏览器兼容)
    JS页面刷新实现方法总结
    php 一些常用的语句
    使用ZeroClipboard解决跨浏览器复制到剪贴板的问题
    window.opener.location.reload() and href()的区别 弹出页修改后刷新父窗体
    查看Mysql数据库大小
    JQUERY操作集锦
    十进制正整数转换成六十二进制
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/13613179.html
Copyright © 2020-2023  润新知