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.
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
链接: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; }