1. 程式人生 > >HDU5579 LCM & 唯一分解定理 & 排列組合

HDU5579 LCM & 唯一分解定理 & 排列組合

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,問你有多少有序陣列(x,y,z)滿足GCD(x,y,z)=G,LCM(x,y,z)=L,首先如果gcd(x,y,z)=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種排列之外,其餘的(0,x,t)(1<=x<=t-1)有6種排列。

          對於某一個素因子p總的方法數為6*(t-1)+2*3=6*t。

  在根據組合排列的知識,素數與素數之間是分步的關係,因而總的方法數為:6*t1*6*t2*6*t3*...*6*tn

程式碼:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
using namespace std;
typedef long long LL;
const int maxn = 2e5;
int p[maxn];
int main()
{
    int T;
    scanf("%d", &T);

    while(T--)
    {
        LL L, G;
        scanf("%lld%lld", &G, &L);
        LL temp = L/G;
        int x = sqrt(temp+0.5);
        memset(p, 0, sizeof(p));
        for(int i = 2; i <= x; i++)
        {
            while(temp%i ==0)
            {
                temp/=i;
                p[i]++;
            }
        }
        LL ans;
        if(temp != 1) ans = 6;//如果L/G本身是素數
        else ans = 1;
        for(int i = 2; i <= x; i++)
        {
            if(p[i])
                ans *= p[i]*6;
        }
        if(L%G)
            printf("0\n");
        else
            printf("%lld\n", ans);
    }
    return 0;
}