Hankson的趣味题

雨燕双飞 提交于 2020-03-15 11:21:13

【题目描述】
今天在课堂上,老师讲解了如何求两个正整数c[1]和c[2]的最大公约数和最小公倍数。现
在Hankson认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公
倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a[0]、a[1]、b[0]、b[1],设某未知正整
数x满足:
1.x和a[0]的最大公约数是a[1];
2.x和b[0]的最小公倍数是b[1]。
Hankson的“逆问题”就是求出满足条件的正整数x。但稍加思索之后,他发现这样的
x并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的x的个数。请你帮
助他编程求解这个问题。

【输入描述】

第一行为一个正整数n,表示有n组输入数据。接下来的n行每行一组输入数据,为四个正整数a[0]、a[1]、b[0]、b[1],每两个整数之间用一个空格隔开。输入数据保证a[0]能被a[1]整除,b[1]能被b[0]整除。

【输出描述】
每组输入数据的输出结果占一行,为一个整数。
对于每组数据:若不存在这样的x,请输出0;
若存在这样的x,请输出满足条件的x 的个数。

【样例输入】
2
41 1 96 288
95 1 37 1776

【样例输出】
6
2

【数据范围及提示】
样例解释:
第一组输入数据,x可以是9、18、36、72、144、288,共有6个;
第二组输入数据,x可以是48、1776,共有2个。
数据范围:
对于50%的数据,保证有1 ≤ a[0],a[1],b[0],b[1] ≤ 10000且n ≤ 100;
对于100%的数据,保证有1 ≤ a[0],a[1],b[0],b[1] ≤ 2000000000且n ≤ 2000。

源代码:

#include<cstdio>
int n,A0,A1,B0,B1;
int GCD(int t1,int t2)
{
    return t2==0?t1:GCD(t2,t1%t2);
}
bool Judge(int t)
{
    if (t%A1)
      return 0;
    return GCD(t/A1,A0/A1)==1&&GCD(B1/B0,B1/t)==1; //皆为同理。
}
int main()
{
    scanf("%d",&n);
    for (int a=1;a<=n;a++)
    {
        scanf("%d%d%d%d",&A0,&A1,&B0,&B1);
        long long ans=0; //线上游戏的Long Long不可能不坑爹。
        for (int b=1;b*b<=B1;b++) //能够不重复整除的范围。
        {
            if (!(B1%b)) //判断是否为因数。
            {
                ans+=Judge(b);
                if (B1/b!=b) //可以减少枚举次数。
                  ans+=Judge(B1/b);
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

/*
    我是数论绽放后的余烬——
    蛤蛤蛤蛤蛤太弱了蛤蛤蛤蛤蛤。
        lcm(x,B0) = x*B0/gcd(x,B0) = B1;
        gcd(x,B0) = x*B0/B1;
        gcd(x/(x*B0/B1),B0/(x*B0/B1)) = 1;
        最终得:gcd(B1/B0,B1/x) = 1,到此,只需枚举B1的因数就行了。
*/

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!