HDU 4497GCD and LCM(素數分解)

果7發表於2013-08-26

GCD and LCM

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 188    Accepted Submission(s): 94


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
 

Source
 

                 題目大意:找出三個數,他們的gcd是g他們的lcm是l。問你有多少組這樣的數字。

          解題思路:如果想到把兩個數分解成素數,會很簡單。g分解成a1^n1*a2^n2*a3^n3...l也分解成b1^m1*b2^m2...
會發現l的因子必須把g的因子含進去,不光是類別而且是每個類的數目。我們可以直接判別l%g!=0的話就直接輸出0. l%g==0的話l=l/g。然後只需要對l分解成素數即可。l=b1^m1*b2^m2...假設三個數滿足題目的條件則有lcm(q1,q2,q3)=l gcd(q1,q2,q3)=1,設這三個數為q1,q2,q3,q1=b1^s1*q2^s4...,q2=b1^s2*q2^s5...,q3=b1^s3*q2^s6.
         由於lcm(q1,q2,q3)=l gcd(q1,q2,q3)=1 所以min(s1,s2,s3)=0,max(s1,s2,s3)=m1.s1取0,s2取m1,s3取1~m1,這樣的共有(m1-1)*6,6是排列數。s1,s2取0,s3取m1的共有3。  s1,s2取m1,s3取0的也有3種。 以上三種情況裡的s1,s2,s3順序可以排列,所以已經乘上了組合數。三者相加便是6*m1。然後依次其它計算方式一樣然後答案就是6*m1*6*m2*6*m3.....詳見程式碼。(開始準備素數打表,T總共才12無需打標)

          題目地址:GCD and LCM

AC程式碼:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;

int isprim(int x)  //判定是素數
{
    int flag=1,i;
    for(i=2;i<=sqrt(x+0.5);i++)
        if(x%i==0)
        {
            flag=0;
            break;
        }
    return flag;
}

int main()
{
    int tes,g,l,i;
    scanf("%d",&tes);
    while(tes--)
    {
        scanf("%d%d",&g,&l);
        if(l%g!=0) puts("0");
        else
        {
             l=l/g;
             __int64 sum;
             sum=1;
             for(i=2;i<=sqrt(l+0.5);i++)
                if(isprim(i)&&(l%i==0))
                {
                     int p=0;
                     while(l%i==0)
                     {
                         l/=i;
                         p++;
                     }
                     sum=sum*6*p;  //剛推的式子
                }
            if(l>1) sum*=6;  //比如說9999997這樣的數
            printf("%I64d\n",sum);
        }
    }
    return 0;
}



相關文章