3071: 【普及+/提高】【P1072】Hankson 的趣味题

内存限制:128 MB 时间限制:1.000 S
评测方式:文本比较 命题人:
提交:1 解决:1

题目描述

Hanks 博士是 BT(Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫 Hankson。现在,刚刚放学回家的 Hankson 正在思考一个有趣的问题。

今天在课堂上,老师讲解了如何求两个正整数 lns="http://www.w3.org/1998/Math/MathML">1 和 lns="http://www.w3.org/1998/Math/MathML">2 的最大公约数和最小公倍数。现在 Hankson 认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数 lns="http://www.w3.org/1998/Math/MathML">0,1,0,1,设某未知正整数 lns="http://www.w3.org/1998/Math/MathML"> 满足:

  1. lns="http://www.w3.org/1998/Math/MathML"> 和 lns="http://www.w3.org/1998/Math/MathML">0 的最大公约数是 lns="http://www.w3.org/1998/Math/MathML">1

  2. lns="http://www.w3.org/1998/Math/MathML"> 和 lns="http://www.w3.org/1998/Math/MathML">0 的最小公倍数是 lns="http://www.w3.org/1998/Math/MathML">1

Hankson 的“逆问题”就是求出满足条件的正整数 lns="http://www.w3.org/1998/Math/MathML">。但稍加思索之后,他发现这样的 lns="http://www.w3.org/1998/Math/MathML"> 并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的 lns="http://www.w3.org/1998/Math/MathML"> 的个数。请你帮助他编程求解这个问题。

【样例解释】

第一组输入数据,lns="http://www.w3.org/1998/Math/MathML"> 可以是 lns="http://www.w3.org/1998/Math/MathML">9,18,36,72,144,288,共有 lns="http://www.w3.org/1998/Math/MathML">6 个。

第二组输入数据,lns="http://www.w3.org/1998/Math/MathML"> 可以是 lns="http://www.w3.org/1998/Math/MathML">48,1776,共有 lns="http://www.w3.org/1998/Math/MathML">2 个。

【数据范围】

  • 对于 lns="http://www.w3.org/1998/Math/MathML">50% 的数据,保证有 lns="http://www.w3.org/1998/Math/MathML">10,1,0,110000 且 lns="http://www.w3.org/1998/Math/MathML">100
  • 对于 lns="http://www.w3.org/1998/Math/MathML">100% 的数据,保证有 lns="http://www.w3.org/1998/Math/MathML">10,1,0,12×109 且 lns="http://www.w3.org/1998/Math/MathML">2000

输入

第一行为一个正整数 lns="http://www.w3.org/1998/Math/MathML">,表示有 lns="http://www.w3.org/1998/Math/MathML"> 组输入数据。接下来的lns="http://www.w3.org/1998/Math/MathML"> 行每行一组输入数据,为四个正整数 lns="http://www.w3.org/1998/Math/MathML">0,1,0,1,每两个整数之间用一个空格隔开。输入数据保证 lns="http://www.w3.org/1998/Math/MathML">0 能被 lns="http://www.w3.org/1998/Math/MathML">1 整除,lns="http://www.w3.org/1998/Math/MathML">1 能被 lns="http://www.w3.org/1998/Math/MathML">0 整除。

输出

共 lns="http://www.w3.org/1998/Math/MathML"> 行。每组输入数据的输出结果占一行,为一个整数。

对于每组数据:若不存在这样的 lns="http://www.w3.org/1998/Math/MathML">,请输出 lns="http://www.w3.org/1998/Math/MathML">0,若存在这样的 lns="http://www.w3.org/1998/Math/MathML">,请输出满足条件的 lns="http://www.w3.org/1998/Math/MathML"> 的个数;

样例输入 复制

2 
41 1 96 288 
95 1 37 1776 

样例输出 复制

6
2

提示

#include <bits/stdc++.h>
using namespace std;

// 最大公约数
int gcd(int a, int b) {
    return b ? gcd(b, a % b) : a;
}

// 最小公倍数
int lcm(int a, int b) {
    return b / gcd(a, b) * a; // 注意顺序,防止乘法爆int
}

int main() {
    int T;
    cin >> T;
    while (T--) {
        int ans = 0, a0, a1, b0, b1;
        cin >> a0 >> a1 >> b0 >> b1;
        /*
            读入四个数字
            x 和 a0 的最大公约数是 a1
            x 和 b0 的最小公倍数是 b1
        */
        for (int i = 1; i * i <= b1; i++) {                  // 枚举b1的所有约数
            if (b1 % i) continue;                            // 是因数
            if (gcd(i, a0) == a1 && lcm(i, b0) == b1) ans++; // 因数i符合要求
            int j = b1 / i;                                  // 另一个因子
            if (gcd(j, a0) == a1 && lcm(j, b0) == b1 && i != j) ans++;
        }
        printf("%d\n", ans);
    }
    return 0;
}