GCD and LCM
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 214 Accepted Submission(s): 105
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
Source
Recommend
liuyiding
题意:
给你三个数的最大公约数g和最小公倍数问你满足条件的这三个数有多少种。
思路:
来源于大神博客见此
将满足条件的一组x,z,y都除以G,得到x‘,y',z',满足条件gcd(x',y',x') = 1,同时lcm(x',y',x') = G/L.(转化很经典)
特判,当G%L != 0 时,无解。
然后素数分解G/L,假设G/L = p1^t1 * p2^t2 *````* pn^tn。
满足上面条件的x,y,z一定为这样的形式。
特判,当G%L != 0 时,无解。
然后素数分解G/L,假设G/L = p1^t1 * p2^t2 *````* pn^tn。
满足上面条件的x,y,z一定为这样的形式。
x' = p1^i1 * p2^i2 *```* pn^in.
y' = p1^j1 * p2^j2 * ```*pn^jn.
z' = p1^k1 * p2^k2 * ```*pn^kn.
为了满足上面的条件,对于p1,一定有max(i1,j1,k1) = t1.min(i1,j1,k1) =0;则当选定第一个数为0,第二个数为t1时,第三个数可以为0-t1,又由于有顺序的,只有
(0,t1,t1) 和(0,t1,0)这两种情形根据顺序只能产生6种结果,其他的由于三个数都不一样,一定能产生6种,所以最后产生了6*(t1-1)+3*2 = 6*t1种(t1-1是因为t1从0开始所以一共有t1+1个数除去0.和t1还剩t1-1个数),根据乘法原理以及关于素数分解的唯一性,反过来,素数组合必然也是唯一的数,一共有6*t1 * 6*t2 *`````*6*tn种选法。
详细见代码:
#include <iostream>
#include<stdio.h>
#include<map>
using namespace std;
const int maxn=10000100;
int cnt;
int fac[100][2];
void getprime(int x)
{
int i;
cnt=0;
for(i=2; i<maxn; i++)
{
if(x%i==0)
{
fac[cnt][0]=i;
fac[cnt][1]=1;
x/=i;
while(x%i==0)
{
fac[cnt][1]++;
x/=i;
}
cnt++;
}
if(x==1)
break;
}
}
int main()
{
int t,g,l,i,ans;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&g,&l);
if(l%g!=0)
{
printf("0\n");
continue;
}
getprime(l/g);
ans=1;
for(i=0;i<cnt;i++)
ans*=6*fac[i][1];
printf("%d\n",ans);
}
return 0;
}
另一种思考:容斥原理,对于p1,一共有(t1+1)^3种,但是没有最高位t1的选法是不合法的,减去,一共有t1^3种选法不合法,没有最低位0的选法是不合法的,也是t1^3,发现多减了,所以加上多减的既没有最高位也没有最低位的(t1-1)^3,通过化简得6*t1`````
详细见代码:
#include <iostream>
#include<stdio.h>
#include<map>
using namespace std;
const int maxn=1000010;
int cnt;
int fac[100][2],a[100],ptr;
map<int,int> mp1,mp2;
void getprime(int x)
{
int i;
cnt=0;
for(i=2; i<maxn*10; i++)
{
if(x%i==0)
{
fac[cnt][0]=i;
fac[cnt][1]=1;
x/=i;
while(x%i==0)
{
fac[cnt][1]++;
x/=i;
}
cnt++;
}
if(x==1)
break;
}
}
int main()
{
int t,g,l,i,m1,m2,ans;
long long sum,tmp;
bool flag;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&g,&l);
mp1.clear();
mp2.clear();
flag=false;
getprime(l);
ptr=cnt;
for(i=0;i<cnt;i++)
{
mp1[fac[i][0]]=fac[i][1];
a[i]=fac[i][0];
}
getprime(g);
for(i=0;i<cnt;i++)
{
if(fac[i][1]>mp1[fac[i][0]])
{
flag=true;
break;
}
mp2[fac[i][0]]=fac[i][1];
}
if(flag)
{
printf("0\n");
continue;
}
ans=1;
for(i=0;i<ptr;i++)
{
sum=0;
m1=mp1[a[i]];
m2=mp2[a[i]];
if(m1==m2)
continue;
//printf("%d %d %d\n",a[i],m1,m2);
tmp=m1-m2+1;
sum+=tmp*tmp*tmp;
tmp=m1-m2;
sum-=2*tmp*tmp*tmp;
tmp=m1-m2-1;
sum+=tmp*tmp*tmp;
ans*=sum;
}
printf("%d\n",ans);
}
return 0;
}