GCD and LCM(质因子分解+组合数学)

GCD and LCM

 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

题意:

给定一个G,L,问一共有多少组(x,y,z),可以满足gcd(x,y,z) = G, lcm(x,y,z) = L

(其中(x,y,z)变换顺序算作不同的方案)

分析:

这道题我在做的时候犯了严重的错误!!(反正就是菜)

我使用了公式

lcm(x,y,z)=xyzgcd(x,y,z) l c m ( x , y , z ) = x ⋅ y ⋅ z g c d ( x , y , z )

一定要注意呀,这个公式是不成立的,对于三个及以上的数这个公式是不成立的

它只对两个数求最小公倍数有效

即: lcm(x,y)=xygcd(x,y) l c m ( x , y ) = x ⋅ y g c d ( x , y )


那么下面我们来看一下这道正解应该怎么做

刚才提到了,对于求最小公倍数,上面式子不成立

那么我们就要介绍一下基于算术基本定理的gcd和lcm公式(三个数及以上)

我们就以求三个数x,y,z的gcd和lcm为例:

根据算术基本定理我们得到:

x=pa11pa22parr x = p 1 a 1 ⋅ p 2 a 2 ⋯ p r a r

y=pb11pb22pbrr y = p 1 b 1 ⋅ p 2 b 2 ⋯ p r b r

y=pc11pc22pcrr y = p 1 c 1 ⋅ p 2 c 2 ⋯ p r c r

当然了他们之间也可以存在不同的质因数,我们这里为了讲题方便,故让他们拥有相同质因子,不同幂次

那么三个数的最大公因数和最小公倍数分别为:

gcd(x,y,z)=pmin(a1,b1,c1)1pmin(a2,b2,c2)2pmin(ar,br,cr)r g c d ( x , y , z ) = p 1 m i n ( a 1 , b 1 , c 1 ) ⋅ p 2 m i n ( a 2 , b 2 , c 2 ) ⋯ p r m i n ( a r , b r , c r )

其中 p1,p2.....pr p 1 , p 2 . . . . . p r 是指三个数中所有不同的质因子,因此我们因为取的是最小幂次,故我们可以知道有的幂次为0(即该素因子并不同时存在于三个数中时)

lcm(x,y,z)=pmax(a1,b1,c1)1pmax(a2,b2,c2)2pmax(ar,br,cr)r l c m ( x , y , z ) = p 1 m a x ( a 1 , b 1 , c 1 ) ⋅ p 2 m a x ( a 2 , b 2 , c 2 ) ⋯ p r m a x ( a r , b r , c r )

同样, p1,p2.....pr p 1 , p 2 . . . . . p r 是指三个数中所有不同的质因子

这样一来

对于给定的G和L,我们就可以知道每一个质因数在三个数中的最小指数和最大指数

比如
G=pe11pe22perr G = p 1 e 1 ⋅ p 2 e 2 ⋯ p r e r

L=pw11pw22pwrr L = p 1 w 1 ⋅ p 2 w 2 ⋯ p r w r

我们假设q是第三个指数,即那个中间值

min(ei,qi,wi)=ei m i n ( e i , q i , w i ) = e i

max(ei,qi,wi)=wi m a x ( e i , q i , w i ) = w i

很明显 qi q i 必须在 [ei,wi] [ e i , w i ] 之间

下面我们进行分类讨论:

(1) qi q i 的值既不等于 ei e i 也不等于 wi w i ,即 qi(ei,wi) q i ∈ ( e i , w i ) :

此时共有 wiei1 w i − e i − 1 种选择,而且题目中说了,相同数字顺序不同算不同情况,所以对于三个互不相同的数字一共有A(3,3)种情况

ans=A(3,3)×(wiei1)=6×wiei1) a n s = A ( 3 , 3 ) × ( w i − e i − 1 ) = 6 × ( w i − e i − 1 )

(2) qi q i 的值等于 ei e i 或者 wi w i 时,首先他有两种选择,那么对于给定三个数字中两个有相同的数字的排列方式,一共有A(3,1)种

即ans = 3 × 2 种

综上对于一个素因子来说它的可选择的方案为上述两种情况加起来

ans=6×(wiei) a n s = 6 × ( w i − e i )

那么根据乘法原理,对于所有的素因子来说,所有的可能数便是每个素因子的

ans=6×(wiei) a n s = 6 × ( w i − e i )

相乘得到的结果

注意:!!!!!

如果当 wi w i ei e i 相等时,根据公式 ans=6×(wiei) a n s = 6 × ( w i − e i ) ,此时为0,那么如果一乘就全没了,那么此时我们需要特判,即这种情况下,三个指数相同,那么只有一种情况,相当于乘1,直接跳过即可

好题鸭,可能是因为太菜。。(大佬们觉得这是水题。。。)
code:

#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
ll w[maxn][2],e[maxn][2],cntG,cntL;
void divide(int G,int L){
    cntG = cntL = 0;
    for(int i = 2; i * i <= G; i++){
        if(G % i == 0){
            e[cntG][0] = i;
            e[cntG][1] = 0;
            while(G % i == 0){
                e[cntG][1]++;
                G /= i;
            }
            cntG++;
        }
    }
    if(G != 1){
        e[cntG][0] = G;
        e[cntG++][1] = 1;
    }
    for(int i = 2; i * i <= L; i++){
        if(L % i == 0){
            w[cntL][0] = i;
            w[cntL][1] = 0;
            while(L % i == 0){
                w[cntL][1]++;
                L /= i;
            }
            cntL++;
        }
    }
    if(L != 1){
        w[cntL][0] = L;
        w[cntL++][1] = 1;
    }
}
ll solve(int G,int L){
    if(L % G != 0) return 0;
    divide(G,L);
    ll ans = 1;
    ll v;
    for(int i = 0; i < cntL; i++){//遍历枚举找相同素因子
        int flag = 0;
        for(int j = 0; j < cntG; j++){
            if(w[i][0] == e[j][0]){//找到相同质因子
                flag = 1;
                v = j;//记录下位置
                break;
            }
        }
        if(!flag) ans = ans * 6 * w[i][1];//如果找不到与lcm中相同的质因子,说明在gcd中该质因子指数为0
        else{//如果找到
            ll t = w[i][1] - e[v][1];
            if(!t) continue;//如果相减为0,不能乘,相当于只有1种,直接跳过即可
            ans = ans * 6 * t;//否则按照推导公式求
        }
    }
    return ans;
}
int main(){
    int T;
    int G,L;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&G,&L);
        ll ans = solve(G,L);
        printf("%lld\n",ans);
    }
    return 0;
}

你可能感兴趣的:(组合数学,数论)