Luogu P1072 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

说明

第一组输入数据,x可以是9、18、36、72、144、288,共有6个。
第二组输入数据,x可以是48、1776,共有2个。

注释说明

对于50%的数据,保证有1≤a0,a1,b0,b1≤10000且n≤100。
对于100%的数据,保证有1≤a0,a1,b0,b1≤2,000,000,000且n≤2000。

#include<cstdio>
using namespace std;
typedef long long ll;

ll n,a0,a1,b0,b1,ans=1;

ll prime[500005],cnt;

bool off[500005];

inline void input(ll &x){
	ll ans=0,f=1;
	char c=getchar();
	while(c>'9'||c<'0'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		ans=ans*10+ll(c-48);
		c=getchar();
	}
	x=ans*f;
}

inline void output(ll x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)output(x/10);
	putchar(char(x%10+48));
}

inline void euler(){
	off[0]=off[1]=1;	
	for(ll i=1;i<=50000;i++){
		if(!off[i])prime[++cnt]=i;
		for(ll j=1;j<=cnt&&i*prime[j]<=50000;j++){
			off[i*prime[j]]=1;
			if(i%prime[j]==0)break;
		}	
	}	
}

inline void work(ll x){
	ll ina0=0,ina1=0,inb0=0,inb1=0;
	while(a0%x==0)a0/=x,ina0++;
	while(a1%x==0)a1/=x,ina1++;
	while(b0%x==0)b0/=x,inb0++;
	while(b1%x==0)b1/=x,inb1++;
	if(ina0<ina1||inb0>inb1)ans=0;
	if(ina0>ina1){
		if(inb0<inb1){
			if(ina1==inb1)ans*=1;else ans=0;
		}
		else if(inb0==inb1){
			if(ina1<=inb1)ans*=1;else ans=0;
		}
	}
	if(ina0==ina1){
		if(inb0<inb1){
			if(ina1<=inb1)ans*=1;else ans=0;
		}
		else if(inb0==inb1){
			if(ina1<=inb1)ans*=(inb1-ina1)+1;
			else ans=0;
		}
	}
}

int main(){
	euler();
	input(n);
	for(ll i=1;i<=n;i++){
		ans=1;		
		input(a0);input(a1);input(b0);input(b1);
		//gcd(x,a0)=a1;
		//lcm(x,b0)=b1;
		for(ll i=1;i<=cnt;i++){
			work(prime[i]);
		}
		if(b1!=1)work(b1);
		output(ans);
		putchar('\n');
	}	
}
posted @ 2019-03-29 21:00  Y15BeTa  阅读(237)  评论(0编辑  收藏  举报