GCD and LCM
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 2982 Accepted Submission(s):
1305
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.
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.
题目大意:
求gcd(x,y,z)=G且lcm(x,y,z)=L的方法数。
题目分析:
起初这道题一点想法都没有。。看了题解才有些想法。
首先如果L不能被G整除的话,这样的组合一定不存在。
当这样的组合存在的时候,所求与 求gcd(x,y,z)=1且lcm(x,y,z)=L/G的方法数是等价的。
那么:令temp=L/G。
对temp进行素数分解:temp=p1^t1 * p2^t2 * ……* pn^tn。
因为temp是这三个数的倍数,因而x,y,z的组成形式为:
x=p1^i1 * p2^i2 *…… * pn^in;
y=p1^j1 * p2^j2 *…… * pn^jn;
z=p1^k1 * p2^k2 * …… * pn^kn;
对于某一个素因子p:
因为要满足x,y,z的最大公约数为1,即三个数没有共同的素因子,所以min(i,j,k)=0。
又因为要满足x,y,z的最小公倍数为temp,即p^t必然要至少存在一个,所以max(i,j,k)=t。
换言之:至少要有一个p^t,以满足lcm的要求;至多有两个包含p,以满足gcd的要求。
因而基本的组合方式为(0,p^t,p^k),k=0-->t。
而因为(1,2,3)和(2,1,3)是不同的方法,所有满足要求的方法中,除了(0,0,t)和(0,t,t)
各有3种排列之外,其余都有6种排列。
对于某一个素因子p总的方法数为6*(t-1)+2*3=6*t。
在根据组合排列的知识,素数与素数之间是分步的关系,因而总的方法数为:6*(t1+t2+……+tn)
对于某个r,i、j、k里面一定有一个是r,并且一定有一个是0,所以i,j,k有一下3种情况:
r 0 0 ,有C(3,1)种
r 0 r ,有C(3,1)种
r 0 1~r-1 ,有(r-1)*A(3,3)种
所以一共是6*r种。
1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <algorithm> 5 int map[6000]; 6 int n, m, sum; 7 int main() 8 { 9 int i, j, k, sum; 10 scanf("%d", &k); 11 while (k--) 12 { 13 scanf("%d%d", &n, &m); 14 if (m%n) 15 { 16 printf("0 "); 17 continue; 18 } 19 memset(map, 0, sizeof(map)); 20 m = m / n; 21 j = 0; 22 for (i = 2; i*i <= m; i++)//分解质因数m,i<sqrt(m) 23 { 24 if (m%i == 0) 25 { 26 while (m%i == 0) 27 { 28 map[j]++; 29 m = m / i; 30 } 31 j++; 32 } 33 } 34 if (m != 1) 35 map[j++] = 1; 36 //样例6,72,m为12,分解为2个2,1个3,(6*2)*(6*1) 37 sum = 1; 38 for (i = 0; i<j; i++) 39 sum = sum * 6 * map[i]; 40 printf("%d ", sum); 41 } 42 return 0; 43 }