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.
 

 

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
 告诉了三个数的最大公约数和最小公倍数,要你求出这三个数字有多少种可能(次序不同,排列不同)
先想想两个数字之间的关系是什么?
如果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 }

 

posted @ 2018-03-20 20:03  zero1998  阅读(446)  评论(0编辑  收藏  举报