首页 > 技术文章 > P1072Hankson 的趣味题(gcd好题!枚举判断可行)

MYMYACMer 2021-05-25 10:30 原文

传送门

今天在课堂上,老师讲解了如何求两个正整数 c1 和 c2 的最大公约数和最小公倍数。

现在 Hankson 认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a0,a1,b0,b1,设某未知正整数 x 满足:

1. x 和 a0 的最大公约数是 a1

2. x 和 b0 的最小公倍数是 b1

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

思路:把x分解为a*b,b0分解为a*c,则b1=a*b*c,b与c互素,b=b1/b0,我们可以枚举a的取值情况,得到一个x=a*b,然后再去判断gcd(x,a0)是否等于a1,想清楚就非常简单!

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 10001000;
const int inf = 0x3f3f3f3f;
const ll mod = 100000000;
ll a0, a1, b0, b1;
ll gcd(ll m, ll n) {
    return n == 0 ? m : gcd(n, m % n);
}
int main() {
    //freopen("test.txt", "r", stdin);
    int t; scanf("%d", &t);
    while (t--) {
        scanf("%lld%lld%lld%lld", &a0, &a1, &b0, &b1);
        ll b = b1 / b0;
        ll t = sqrt(b0);
        int ans = 0;
        for (int i = 1; i <= t; i++) {
            if (b0 % i == 0) {//找到一组a,b,即(i,b0/i);
                if (gcd(b, b0 / i) == 1&&gcd(i*b,a0)==a1) {//a=i
                    ans++;
                }
                if (b0!=i*i&&gcd(b, i) == 1 && gcd((b0 / i) * b, a0) == a1) {//a=b0/i
                    ans++;
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

推荐阅读