GCD and LCM
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)
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.
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.
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
题目大意:给定三个数的最大公约数和最小公倍数,求这三个数的所有组合个数?
只知道应该将l/g分解成素数的次方之积(后来才知道是 整数唯一分解定理),但是不知道如何给这三个数分配各素数
看了题解才明白,要学会分析
由于x,y,z均含有因子g,所以只用讨论x/g,y/g,z/g这三个数的取值即可
设l/g中某一素数p的指数为cnt,则只有满足这三个数中至少有一个数的p的指数为cnt(否则最小公倍数不是l),至少有一个数的p的指数为0(否则最大公约数不是1)
共三种情况:①一个数的p的指数为cnt,一个数的p的指数为0,另一个数的p的指数取1~cnt-1,方案数为:C(3,1)*C(2,1)*(cnt-1)
②两个数的p的指数为cnt,一个数的p的指数为0,方案数为:C(3,1)
③一个数的p的指数为cnt,两个个数的p的指数为0,方案数为:C(3,1)
则一个指数为cnt的素数p能产生的方案数为:6*cnt
注意:如果存在素数大于10^5,则必定只有一个,且其指数为1
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=100005;
int n,m,g,l,cnt,ans;
int prime[MAXN+4];
void getPrime() {
memset(prime,0,sizeof(prime));
for(int i=2,lim;i<=MAXN;++i) {
if(prime[i]==0) {
prime[++prime[0]]=i;
}
lim=MAXN/i;
for(int j=1;j<=prime[0]&&prime[j]<=lim;++j) {
prime[prime[j]*i]=1;
if(i%prime[j]==0) {
break;
}
}
}
}
int main(){
int T;
getPrime();
scanf("%d",&T);
while(T-->0) {
scanf("%d%d",&g,&l);
if(l%g!=0) {
printf("0\n");
}
else {
ans=1;
l/=g;
for(int i=1;i<=prime[0];++i) {
if(l%prime[i]==0) {
cnt=0;
while(l%prime[i]==0) {//统计素数的指数
++cnt;
l/=prime[i];
}
ans*=6*cnt;
}
}
if(l>1) {//如果存在素数大于10^5,则必定只有一个,且其指数为1
ans*=6;
}
printf("%d\n",ans);
}
}
return 0;
}