hdu 4497 GCD and LCM 数论 素数分解

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; 
} 





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值