题目描述
HanksHanks 博士是 BTBT(Bio-TechBio−Tech,生物技术) 领域的知名专家,他的儿子名叫 HanksonHankson。现在,刚刚放学回家的 HanksonHankson 正在思考一个有趣的问题。
今天在课堂上,老师讲解了如何求两个正整数c_1c1 和 c_2c2 的最大公约数和最小公倍数。现在 HanksonHankson 认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a_0,a_1,b_0,b_1a0,a1,b0,b1,设某未知正整数xx 满足:
1. xx 和 a_0a0 的最大公约数是 a_1a1;
2. xx 和 b_0b0 的最小公倍数是b_1b1。
HanksonHankson 的“逆问题”就是求出满足条件的正整数xx。但稍加思索之后,他发现这样的xx 并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的 xx 的个数。请你帮助他编程求解这个问题。
输入输出格式
输入格式:
第一行为一个正整数 nn,表示有 nn 组输入数据。接下来的nn 行每行一组输入数据,为四个正整数 a_0,a_1,b_0,b_1a0,a1,b0,b1,每两个整数之间用一个空格隔开。输入数据保证 a_0a0 能被 a_1a1 整除,b_1b1 能被b_0b0整除。
输出格式:
共 nn行。每组输入数据的输出结果占一行,为一个整数。
对于每组数据:若不存在这样的 xx,请输出 00;
若存在这样的xx,请输出满足条件的xx 的个数;
输入输出样例
说明
【说明】
第一组输入数据,xx可以是 9,18,36,72,144,2889,18,36,72,144,288,共有66 个。
第二组输入数据,xx 可以是48,177648,1776,共有 22 个。
【数据范围】
对于 50%的数据,保证有 1≤a_0,a_1,b_0,b_1≤100001≤a0,a1,b0,b1≤10000 且n≤100n≤100。
对于 100%的数据,保证有 1≤a_0,a_1,b_0,b_1≤2,000,000,0001≤a0,a1,b0,b1≤2,000,000,000 且 n≤2000n≤2000。
NOIP 2009 提高组 第二题
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int N=105; const int M=44800; inline long long read() { char c=getchar();long long num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } int gcd(int a,int b) { int g; while(b) { g=a; a=b; b=g%b; } return a; } long long n,a0,a1,b0,b1,x; int main() { n=read(); int ans,tmp; while(n--) { ans=0; a0=read(),a1=read(),b0=read(),b1=read(); int bound=(int)sqrt(b1); for(int i=1;i<=bound;++i) { if(b1%i) continue; if(gcd(i,a0)==a1&&gcd(i,b0)*b1==i*b0) ++ans; if(gcd(b1/i,a0)==a1&&gcd(b1/i,b0)*b1==b0*(b1/i)) ++ans; } int a=sqrt(b1); if(a*a==b1) if(gcd(a,a0)==a1&&gcd(a,b0)*b1==b0*a) --ans; printf("%d ",ans); } return 0; }