GCD and LCM
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 1339 Accepted Submission(s): 607
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
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4497
题意:每个案例给你两个数G和L。然后找有多少不同的(x,y,z) 的gcd是G,且lcm是L。
做法:分解素数G,L。
首先 L%G!=0 那肯定是输出0的。
第一个案例 6 72
分解后 6 有一个2,一个3。
72分解后有3个2,2个3。
然后对于素数2, 6的1个2 是下限,72的3个2是上限。 x,y,z 必须有一个数 能分解出一个素数2,必须有另一个数 分解出3个2, 然后剩下的那个数分解出的2的个数必须在【1,3】之间。
然后可以推出 对于素数2 给x,y,z分配素数2 的个数 一共有 6+(3-1 -1)*6 种分法。前面一个6,代表第三个数是和上限或者下限相等的 如 2 2 8 或者 2 8 8 。因为有两个数相等所以他们的排列组合是3种。 所以是2*3=6种。 然后后面的是代表 三个数都不相同的情况,3-1-1 =1说明1至3之间只有一个数,也就是2,也就是分配两个素数2。 然后 2 4 8排列组合,三个都不同,排列组合为6。
所以对于素数2 的分配方法一共有 12种。
然后分配3,一共有6种。
把各个素数的 分配方法数相乘 12*6=72。 就是总的方案数了。
显然对于这题,可以只用分解L/G,然后对于L各个素数的下限全是0。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <stack>
#include <queue>
#include <vector>
#include <deque>
#include <set>
#include <map>
#define ll __int64
__int64 gcd(__int64 a,__int64 b)
{
if(b==0) return a;
return gcd(b,a%b);
}
__int64 lcm(__int64 a,__int64 b)
{
return a/gcd(a,b)*b;
}
#define N 10000000
//prime[0,primenum)
ll prime[1000000], primenum;
bool Isprime[N+10];
//<=Max_Prime的素数
void PRIME(ll Max_Prime){
primenum = 0;
Isprime[0] = Isprime[1] = 0;
Isprime[2] = 1;
prime[primenum++] = 2;
for(ll i = 3; i <= Max_Prime; i++)
Isprime[i] = i&1;
for (ll i = 3; i <= Max_Prime; i+=2){
if(Isprime[i])
prime[primenum++] = i;
for (ll j = 0; j < primenum; j++){
if(prime[j] * i > Max_Prime)break;
Isprime[prime[j]*i] = 0;
if(i%prime[j] == 0)break;
}
}
}
ll fen_g[1000000];
ll fen_l[1000000];
ll vis[1000000];
ll wei[1000000];
int main()
{
PRIME(100000);
__int64 t,g,l;
scanf("%I64d",&t);
while(t--)
{
scanf("%I64d%I64d",&g,&l);
if(l%g!=0)
printf("0\n");
else
{
memset(fen_g,0,sizeof fen_g);
memset(fen_l,0,sizeof fen_l);
memset(vis,0,sizeof vis);
l=l/g;
__int64 tem_g=g;
__int64 tem_l=l;
__int64 ji=0;
for(__int64 i=0;i<primenum;i++)
{
while(tem_l%prime[i]==0)
{
tem_l/=prime[i];
if(fen_l[i]==0&&vis[i]==0)
{
vis[i]=1;
wei[ji++]=i;
}
fen_l[i]++;//上限
}
}
if(tem_l!=1)
{
wei[ji++]=primenum;
vis[primenum]=1;
fen_l[primenum]++;
}
ll ans=1;
for(__int64 i=0;i<ji;i++)
{
__int64 ww=wei[i];
__int64 cnt=fen_l[wei[i]];
if(cnt==1)
{
ans*=6;
}
else
ans*=3*2+(cnt-1)*6;
}
printf("%I64d\n",ans);
}
}
return 0;
}