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)变换顺序算作不同的方案)
分析:
这道题我在做的时候犯了严重的错误!!(反正就是菜)
我使用了公式
一定要注意呀,这个公式是不成立的,对于三个及以上的数这个公式是不成立的
它只对两个数求最小公倍数有效
即:
那么下面我们来看一下这道正解应该怎么做
刚才提到了,对于求最小公倍数,上面式子不成立
那么我们就要介绍一下基于算术基本定理的gcd和lcm公式(三个数及以上)
我们就以求三个数x,y,z的gcd和lcm为例:
根据算术基本定理我们得到:
当然了他们之间也可以存在不同的质因数,我们这里为了讲题方便,故让他们拥有相同质因子,不同幂次
那么三个数的最大公因数和最小公倍数分别为:
其中 是指三个数中所有不同的质因子,因此我们因为取的是最小幂次,故我们可以知道有的幂次为0(即该素因子并不同时存在于三个数中时)
同样, 是指三个数中所有不同的质因子
这样一来
对于给定的G和L,我们就可以知道每一个质因数在三个数中的最小指数和最大指数
比如
我们假设q是第三个指数,即那个中间值
即
很明显 必须在 之间
下面我们进行分类讨论:
(1) 的值既不等于 也不等于 ,即 :
此时共有 种选择,而且题目中说了,相同数字顺序不同算不同情况,所以对于三个互不相同的数字一共有A(3,3)种情况
即
(2) 的值等于 或者 时,首先他有两种选择,那么对于给定三个数字中两个有相同的数字的排列方式,一共有A(3,1)种
即ans = 3 × 2 种
综上对于一个素因子来说它的可选择的方案为上述两种情况加起来
那么根据乘法原理,对于所有的素因子来说,所有的可能数便是每个素因子的
相乘得到的结果
注意:!!!!!
如果当 和 相等时,根据公式 ,此时为0,那么如果一乘就全没了,那么此时我们需要特判,即这种情况下,三个指数相同,那么只有一种情况,相当于乘1,直接跳过即可
好题鸭,可能是因为太菜。。(大佬们觉得这是水题。。。)
code:
#include <iostream>
#include <cstdio>
#include <cstring>
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;
}