HDU - 4497 GCD and LCM

GCD and LCM

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


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

2013 ACM-ICPC吉林通化全国邀请赛——题目重现

题意:

问题描述

给定两个正整数G和L,你能告诉我(x, y, z)有多少个解,满足gcd(x, y, z) = G和lcm(x, y, z) = L?

注意,gcd(x, y, z)表示x、y和z的最大公约数,lcm(x, y, z)表示x、y和z的最小公约数。

注2,(1,2,3)和(1,3,2)是两个不同的解。

输入

第一行是一个整数T (T <= 12),告诉测试用例的数量。

下一行T,每一行都包含两个正的32位有符号整数G和L。
输出

对于每个测试用例,打印一行与满足上述条件的解决方案的数量。

题解:

首先一定有 G | L,在这个条件下,将两个数分解质因子,则一定能得到相同的质因子,且只是指数不同。(Note: 指数可以为 0 & 指数相同的项可以忽略)

即有 G = p1^a1 * p2^a2 * p3^a3 ……, L = p1^b1 * p2^b2 * p3^b3 ……(ai <= bi)。

由于方案的计数符合乘法原理,所以我们只需要考虑对于某个 pi 的方案数,最后相乘即可。

那么对于某个pi,第三个数的取值范围一定是 [a,b],我们分情况来考虑第三个数是否会等于a or b。

1、如果不等于,ans1 = A(3,2) * (b-a-1)。(Note:[a+1,b-1]  =>  cnt = b-a-1)

2、如果等于,ans2 = C(3,1) * 2。

相加可化简为 ans = 6 * (b-a)。

还可以用容斥来考虑,转下。

另一种思考:容斥原理,对于p1,一共有(t1+1)^3种,但是没有最高位t1的选法是不合法的,减去,一共有t1^3种选法不合法,没有最低位0的选法是不合法的,也是t1^3,发现多减了,所以加上多减的既没有最高位也没有最低位的(t1-1)^3,通过化简得6*t1`````

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define N 100000
#define ll long long
using namespace std;
ll d[N][2],e[N][2],cntn,cntm;
void devide(int n,int m){
    cntn=cntm=0;
    for (int i=2; i*i<=n; i++) {
        if (n%i==0) {
            int num=0;
            while (n%i==0) {
                num++;
                n=n/i;
            }
            ++cntn;
            d[cntn][0]=i;d[cntn][1]=num;
        }
    }
    for (int i=2; i*i<=m; i++) {
        if (m%i==0) {
            int num=0;
            while (m%i==0) {
                num=num+1;
                m=m/i;
            }
             ++cntm;
            e[cntm][0]=i,e[cntm][1]=num;
        }
    }
    if (n>1) d[++cntn][0]=n,d[cntn][1]=1;
    if (m>1) e[++cntm][0]=m,e[cntm][1]=1;
}
ll solve(int n,int m){
    if (m%n!=0) return 0;
    devide(n,m );
    ll ans=1,v=0;
    for (int i=1; i<=cntm; i++) {
        int flag=0;
        for (int j=1; j<=cntn; j++) {
            if (e[i][0]==d[j][0]) {
                flag=1;
                v=j;
                break;
            }
        }
        if (!flag) {
            ans=ans*6*e[i][1];
        }else{
            ll t=e[i][1]-d[v][1];
            if (t==0) continue;
            ans=ans*6*t;
        }
    }
    return ans;
}
int main(){
    int T;
    int n,m;
    cin>>T;
    while (T--) {
        cin>>n>>m;
        ll ans=solve(n, m);
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/henu111/article/details/81189103