Hanks博士是BT(Bio-Tech,生物技术)领域的知名专家,他的儿子名叫Hankson。现在,刚刚放学回家的Hankson正在思考一个有趣的问题。今天在课堂上,老师讲解了如何求两个正整数c1c1
和c2c2
的最大公约数和最小公倍数。现在Hankson认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a0,a1,b0,b1a0,a1,b0,b1
,设某未知正整数x满足:1、 x和a0a0
的最大公约数是a1a1
;
2、 x和b0b0
的最小公倍数是b1b1
。Hankson的“逆问题”就是求出满足条件的正整数x。但稍加思索之后,他发现这样的x并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的x的个数。请你帮助他编程求解这个问题。输入格式输入第一行为一个正整数n,表示有n组输入数据。接下来的n行每行一组输入数据,为四个正整数a0,a1,b0,b1a0,a1,b0,b1
,每两个整数之间用一个空格隔开。输入数据保证a0a0
能被a1a1
整除,b1b1
能被b0b0
整除。输出格式输出共n行。每组输入数据的输出结果占一行,为一个整数。对于每组数据:若不存在这样的x,请输出0;若存在这样的x,请输出满足条件的x的个数;数据范围1≤n≤20001≤n≤2000
,
1≤a0,a1,b0,b1≤2∗1091≤a0,a1,b0,b1≤2∗109
输入样例:2
41 1 96 288
95 1 37 1776
输出样例:6
2
思路:枚举d的所有约数看是否符合条件
如何找到d的·1所有约数
先求出d的质因子分解,然后拿质因子筛选,所有质因子在不超过指数的情况下胡乱组合即为所有的约数
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 50010;
int primes[N], cnt;
bool st[N];
struct factor{
int p, s;
}factor[9];
int fcnt;
int dividor[N], dcnt;
void init(int n){
for (int i = 2; i <= n; i ++){
if (!st[i]) primes[cnt ++] = i;
for (int j = 0; primes[j] * i <= n; j ++){
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
void dfs(int u, int p){
if (u == fcnt){
dividor[dcnt ++] = p;
return ;
}
for (int i = 0; i <= factor[u].s; i ++){
dfs(u + 1, p);
p *= factor[u].p;
}
}
int gcd(int a, int b){
return b ? gcd(b, a % b) : a;
}
int main(){
init(N - 1);
int n;
cin >> n;
while(n --){
int a, b, c, d;
cin >> a >> b >> c >> d;
fcnt = 0;
int t = d;
for (int i = 0; primes[i] <= t / primes[i]; i ++){
int p = primes[i];
if (t % p == 0){
int s = 0;
while(t % p == 0) t /= p, s ++;
factor[fcnt ++] = {p, s};
}
}
if (t > 1) factor[fcnt ++] = {t, 1};
dcnt = 0;
dfs(0, 1);
int res = 1;
for (int i = 0; i < dcnt; i ++){
int x = dividor[i];
if (gcd(a, x) == b && (LL)c * x / gcd(c, x) == d) res ++;
}
cout << res << endl;
}
return 0;
}