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)=x⋅y⋅zgcd(x,y,z) l c m ( x , y , z ) = x ⋅ y ⋅ z g c d ( x , y , z )
一定要注意呀,这个公式是不成立的,对于三个及以上的数这个公式是不成立的
它只对两个数求最小公倍数有效
即: lcm(x,y)=x⋅ygcd(x,y) l c m ( x , y ) = x ⋅ y g c d ( x , y )
那么下面我们来看一下这道正解应该怎么做
刚才提到了,对于求最小公倍数,上面式子不成立
那么我们就要介绍一下基于算术基本定理的gcd和lcm公式(三个数及以上)
我们就以求三个数x,y,z的gcd和lcm为例:
根据算术基本定理我们得到:
x=pa11⋅pa22⋯parr x = p 1 a 1 ⋅ p 2 a 2 ⋯ p r a r
y=pb11⋅pb22⋯pbrr y = p 1 b 1 ⋅ p 2 b 2 ⋯ p r b r
y=pc11⋅pc22⋯pcrr y = p 1 c 1 ⋅ p 2 c 2 ⋯ p r c r
当然了他们之间也可以存在不同的质因数,我们这里为了讲题方便,故让他们拥有相同质因子,不同幂次
那么三个数的最大公因数和最小公倍数分别为:
gcd(x,y,z)=pmin(a1,b1,c1)1⋅pmin(a2,b2,c2)2⋯pmin(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)1⋅pmax(a2,b2,c2)2⋯pmax(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=pe11⋅pe22⋯perr G = p 1 e 1 ⋅ p 2 e 2 ⋯ p r e r
L=pw11⋅pw22⋯pwrr 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 ) :
此时共有 wi−ei−1 w i − e i − 1 种选择,而且题目中说了,相同数字顺序不同算不同情况,所以对于三个互不相同的数字一共有A(3,3)种情况
即 ans=A(3,3)×(wi−ei−1)=6×(wi−ei−1) 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×(wi−ei) a n s = 6 × ( w i − e i )
那么根据乘法原理,对于所有的素因子来说,所有的可能数便是每个素因子的
ans=6×(wi−ei) a n s = 6 × ( w i − e i )
相乘得到的结果
注意:!!!!!
如果当 wi w i 和 ei e i 相等时,根据公式 ans=6×(wi−ei) 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;
}