hdu4497 (正数分解定理+排列组合)
题目如下:
GCD and LCM
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 2990 Accepted Submission(s): 1310
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.
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.
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
告诉了三个数的最大公约数和最小公倍数,要你求出这三个数字有多少种可能(次序不同,排列不同)
先想想两个数字之间的关系是什么?
如果L/G!=0,证明找不到这样的三个数字;
如果L/G==0,通过分析得到:gcd(x/g,y/g,z/g)=1&&lcm(x/g,y/g,z/g)=L/G,所以问题就转换成了分解L/G,根据正数分解唯一定理,我们可以把这个数分解为:
假设L/G = 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种选法。
其他的同理。代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 //const int MAXN=100000; 4 #define maxn 1000005 5 int cnt[maxn]; 6 long long ans; 7 void solve(int n) 8 { 9 memset(cnt,0,sizeof(cnt)); 10 int t=sqrt(n*1.0+0.5); 11 for(int i=2;i<=t;i++) 12 { 13 if(n%i==0) 14 { 15 while(n%i==0) 16 { 17 cnt[i]++; 18 n/=i; 19 } 20 } 21 } 22 //int ans=1; 23 if(n!=1)//特殊地方处理,注意一下。列举一下,比如3 24 ans=6; 25 else ans=1; 26 for(int i=2;i<=t;i++) 27 { 28 if(cnt[i]) 29 ans=ans*6*cnt[i]; 30 } 31 } 32 33 34 35 36 37 38 39 int main() 40 { 41 int t ; 42 scanf("%d",&t); 43 while(t--) 44 { 45 ans=1; 46 int n,m; 47 scanf("%d %d",&n,&m); 48 49 if(m%n) 50 cout<<0<<endl; 51 else 52 { 53 n=m/n; 54 solve(n); 55 printf("%I64d\n",ans); 56 } 57 58 59 } 60 61 62 63 64 65 return 0; 66 }