GCD and LCM HDU - 4497 (考最大公约数和最小公倍数的本质了)

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.
InputFirst 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.OutputFor 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 找出 满足 乘积 为 l/g的 三个数且这三个数互质(最大公约为1),还把 l/g 分解成素数相乘,真是,怎么也找不出来;这道题考的是最大公约数 和最小公倍数的 本质;


首先我们可以写出GCD(x,y,z)和LCM(x,y,z)的公式

我们知道任意一个数x可以拆分成x=p1^e1*p2^e2...pk^ek(pi是因质数)

而且GCD(x,y,z)=p1^(min(xe1,ye1,ze1))*p2^(min(xe2,ye2,ze2))...pk^(min(xek,yek,zek))

LCM(x,y,z)=p1^(max(xe1,ye1,ze1))*p2^(max(xe2,ye2,ze2))...pk^(max(xek,yek,zek))

在x,y,z这三个数化为分解素数的乘积时,所有个对于 p ,x ,y,z中,一定有一个 取最大max,一定有一个取最小,另一个就随意取了[min,max],  

当 这个随意取,取(min,max),时,这三个数都不一样,所以由 6中排序当时,因为取的是(min,max),所以6 *(max-min-1);

当 取min时,这三个数中有两个一样的,所以 只有3种排列方式;

当 取max时,同上,有两个一样的,有3中排列方式;

所以由对于每个p,有 6*(max-min-1)+ 3+3 = 6 *(max-min)种;

让这个所有的相乘就是全部的;

max-min 其实是,l/g 化成 素数相乘的 素数的指数;

所以代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define ll long long
#define Max 200005

ll prime[Max];
bool is_prime[Max];
ll sum[Max];
ll tt[Max];

ll num;
ll cot;
void init()
{
	num = 0;
	memset(is_prime,true,sizeof(is_prime));
	
	is_prime[0] = false;
	is_prime[1] = false;
	ll i,j;
	for(i = 2;i<Max;i++)
	{
		if(is_prime[i])
		{
			prime[num++] = i;
			for(j = 2;j*i<Max;j++)
				is_prime[j*i] = false;
		}
	}	
}
void find(long long x)
{
	ll i,j;
	cot =  0;
	for(i = 0;i<num;i++)
	{
		ll pp = 0;
		if(x%prime[i]==0)
		
			while(x%prime[i]==0)
			{
				x /= prime[i];
				pp++;
			}
			sum[cot++] = pp;
		}
	}
	if(x!=1)
		sum[cot++] = 1;
}

int main()
{
	ll i,j,t;
	init();
	scanf("%lld",&t);
	ll g,l;
	while(t--)
	{
		scanf("%lld%lld",&g,&l);
		if(l%g)
			printf("0\n");
		else
		{
			l /= g;
			find(l);
			ll res = 1;
			for(i = 0;i< cot;i++)
				res *=6*sum[i];
			printf("%lld\n",res);
		} 
	}
	return 0;
} 


猜你喜欢

转载自blog.csdn.net/obsorb_knowledge/article/details/80380591
今日推荐