GCD and LCM

http://www.cnblogs.com/allh123/archive/2013/08/24/3279747.html


参考上述两篇文章

GCD and LCM



Problem Description
Given two positive integers G and L, could you tell me how many solutions of (x, y, z) there are, satisfying that gcd(x, y, z) = G and lcm(x, y, z) = L?
Note, gcd(x, y, z) means the greatest common divisor of x, y and z, while lcm(x, y, z) means the least common multiple of x, y and z.
Note 2, (1, 2, 3) and (1, 3, 2) are two different solutions.
 

Input
First line comes an integer T (T <= 12), telling the number of test cases.
The next T lines, each contains two positive 32-bit signed integers, G and L. 
It’s guaranteed that each answer will fit in a 32-bit signed integer.
 

Output
For each test case, print one line with the number of solutions satisfying the conditions above.
 

Sample Input
  
  
2 6 72 7 33
 

Sample Output
  
  
72 0

解题思路:将满足条件的一组x,z,y都除以G,得到x‘,y',z',满足条件gcd(x',y',x') = 1,同时lcm(x',y',x') = G/L.

特判,当G%L != 0 时,无解。

然后素数分解G/L,假设G/L = p1^t1 * p2^t2 *````* pn^tn。

满足上面条件的x,y,z一定为这样的形式。

x' = p1^i1 * p2^i2 *```* pn^in.

y' = p1^j1 * p2^j2 * ```*pn^jn.

z' = p1^k1 * p2^k2 * ```*pn^kn.

为了满足上面的条件,对于p1,一定有max(i1,j1,k1) = t1.min(i1,j1,k1) =0;则当选定第一个数为0,第二个数为t1时,第三个数可以为0-t1,又由于有顺序的,只有

(0,t1,t1) 和(0,t1,0)这两种情形根据顺序只能产生四种结果,其他的由于三个数都不一样,一定能产生6种,所以最后产生了6*(t1-1)+3*2 = 6*t1种,根据乘法原理以及关于素数分解的唯一性,反过来,素数组合必然也是唯一的数,一共有6*t1 * 6*t2 *`````*6*tn种选法。

(上述计算的理解:第一个为0 第二个t1 第三个为0~t1中的一个,三个位置可以相互交换,但是由于当第三个0或者t1的时候,交换位置会有重复,所以没有冲突的情况是6*(t1 - 1),加上 第三个为0是三种情况 第三个是t1的时候是三种情况,所以总共是6*t1种情况)
#include <iostream> #include <map> using namespace std; int findMin(int x) {     for(int i = 2;i <= x;i ++) {         if(x%i == 0) {             return i;         }     }     return -1; } int main() {     int T;     cin >> T;     while(T --) {         int G,L;         cin >> G >> L;         if(L%G != 0) {             cout << 0 << endl;         } else {             int number = L/G;             map<int,int> primeCount;             int t;             while(number != 1) {                 t = findMin(number);                 if(t == -1) {                     break;                 }                 primeCount[t] ++;                 number /= t;             }                          map<int,int>::iterator it;             int result = 1;             for(it = primeCount.begin();it != primeCount.end();it ++) {                 result *= 6 * it->second;             }             cout << result<<endl;         }              }     return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值