Hankson的趣味题
题目描述
Hanks博士是BT(Bio-Tech,生物技术)领域的知名专家,他的儿子名叫Hankson。现在,刚刚放学回家的Hankson正在思考一个有趣的问题。
今天在课堂上,老师讲解了如何求两个正整数c1和c2的最大公约数和最小公倍数。现在Hankson认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a0,a1,b0,b1,设某未知正整数x满足:
1、 x和a0的最大公约数是a1;
2、 x和b0的最小公倍数是b1。
Hankson的“逆问题”就是求出满足条件的正整数x。但稍加思索之后,他发现这样的x并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的x的个数。请你帮助他编程求解这个问题。
输入描述:
第一行为一个正整数n,表示有n组输入数据。接下来的n行每行一组输入数据,为四个正整数a0,a1,b0,b1,每两个整数之间用一个空格隔开。输入数据保证a0能被a1整除,b1能被b0整除。
输出描述:
对于每组数据:若不存在这样的x,请输出0;
若存在这样的x,请输出满足条件的x的个数;
示例1
备注:
对于50%的数据,保证有1≤a0,b1,b0,b1≤10000且n≤100。
对于100%的数据,保证有1≤a0,b1,b0,b1≤2,000,000,000且n≤2000。
题解:
根据lcm的求解方式lcm(a,b)=a*b/gcd(a,b)可以得到 x|b1
于是我们可以枚举b1的约数,只需要特判一下x/b1=x的情况即可
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <string> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cmath> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <vector> 13 #include <ctime> 14 #include <cctype> 15 #include <bitset> 16 #include <utility> 17 #include <sstream> 18 #include <complex> 19 #include <iomanip> 20 #define inf 0x3f3f3f3f 21 typedef long long ll; 22 using namespace std; 23 int n,a0,a1,b0,b1; 24 // x 和a0 的最大公约数是a1 // x 和b0 的最小公倍数是b1 25 int gcd(int a,int b) 26 { 27 return a==0?b:gcd(b%a,a); 28 29 } 30 int lcm(int a, int b) 31 { 32 return a / gcd(a, b) * b; 33 } 34 int main() 35 { 36 scanf("%d",&n); 37 while(n--) 38 { 39 scanf("%d%d%d%d",&a0,&a1,&b0,&b1); 40 int jg = 0 ; 41 for(int i = 1 ; i * i <= b1 ; i ++ ) 42 { 43 jg=0; 44 for(int i = 1; i * i<= b1; i ++) 45 { 46 if(b1 % i == 0) 47 { 48 if(lcm(b0, i) == b1 && gcd(a0, i) == a1) 49 jg ++; 50 int x = b1 / i;//特判一下 51 if(x != i) 52 { 53 if(lcm(b0, x) == b1 && gcd(a0, x) == a1) 54 jg ++; 55 } 56 } 57 } 58 } 59 printf("%d\n",jg); 60 } 61 return 0; 62 }