CH3201 Hankson的趣味题

描述
Hanks博士是BT(Bio-Tech,生物技术)领域的知名专家,他的儿子名叫Hankson。现在,刚刚放学回家的Hankson正在思考一个有趣的问题。
今天在课堂上,老师讲解了如何求两个正整数c1和c2的最大公约数和最小公倍数。现在Hankson认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a0,a1,b0,b1,设某未知正整数x满足:
1、 x和a0的最大公约数是a1;
2、 x和b0的最小公倍数是b1。
Hankson的“逆问题”就是求出满足条件的正整数x。但稍加思索之后,他发现这样的x并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的x的个数。请你帮助他编程求解这个问题。
输入格式
输入第一行为一个正整数n,表示有n组输入数据。接下来的n行每行一组输入数据,为四个正整数a0,a1,b0,b1,每两个整数之间用一个空格隔开。输入数据保证a0能被a1整除,b1能被b0整除。
输出格式
输出共n行。每组输入数据的输出结果占一行,为一个整数。
对于每组数据:若不存在这样的x,请输出0;
若存在这样的x,请输出满足条件的x的个数;
样例输入
2
41 1 96 288
95 1 37 1776
样例输出
6
2

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=44721;
int prime[5010],tot,a,b,c,d,ans;bool v[50010];
void get_prime()
{
	for(int i=2;i<=N;i++)
	{
		if(!v[i])prime[++tot]=i;
		for(int j=1;j<=tot&&i*prime[j]<=N;j++)
		{
			v[i*prime[j]]=1;
			if(i%prime[j]==0)break;
		}
	}
}
int calc(int &x,int p)
{
	int cnt=0;
	while(x%p==0)++cnt,x/=p;
	return cnt;
}
void slove(int p)
{
	int ma,mb,mc,md;
	ma=calc(a,p);
	mb=calc(b,p);
	mc=calc(c,p);
	md=calc(d,p);
	//由最大公因数与最小公倍数的性质判断
	if(ma==mc&&mb==md&&mc<=md)ans*=md-mc+1;
	else if(ma==mc&&md>mb&&mc<=md);
	else if(ma>mc&&md==mb&&mc<=md);
	else if(ma>mc&&md>mb&&mc==md);
	else ans=0;
}
int main()
{
	get_prime();
	int t;scanf("%d",&t);
	for(int i=1;i<=t;i++)
	{
		scanf("%d%d%d%d",&a,&c,&b,&d);
		ans=1;
		for(int j=1;j<=tot&&prime[j]*prime[j]<=d;j++)
		if(d%prime[j]==0)slove(prime[j]);
		if(d>1)slove(d);
		printf("%d\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42886072/article/details/89415188