You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
3.6 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
const int N = 50010;
typedef long long LL;
struct Node {
int prime; // 质数因子
int count; // 个数
} f[10]; // 一维:哪个质数因子,二维:有几个 f:因子
// 根据经验, primes[]={2,3,5,7,11,13,17,19,23}足够分解INT_MAX,共9个就够了
int fl; // 配合数组使用的游标
int d[1610], dl; // 约数数组,约数数组游标 d:约数
// 根据经验INT_MAX中约数个数最多的是1600个,开1610足够。
// 欧拉筛
int primes[N], cnt; // primes[]存储所有素数
bool st[N]; // st[x]存储x是否被筛掉
void get_primes(int n) {
memset(st, 0, sizeof st);
cnt = 0;
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;
}
}
}
// 最大公约数,辗转相除法
int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
}
// 最小公倍数
int lcm(int a, int b) {
return b / gcd(a, b) * a; // 注意顺序防止乘法爆int
}
/**
ufu
p: 1,0base=1
*/
void dfs(int u, int p) {
if (u == fl) { // 如果所有质数因子遍历完成 0~fl-1是所有质因子的下标
d[dl++] = p; // 约数又多了一个
return;
}
// 枚举当前质数因子f[u]使用几个,最少是0个最多是f[u].count个
for (int i = 0; i <= f[u].count; i++) {
dfs(u + 1, p);
p *= f[u].prime; // 这两句话用的太漂亮了完美的模拟了要0个要1个要2个...牛B plus!
}
}
int main() {
get_primes(50000); // 求小的质数因子sqrt(INT_MAX)<50000,开50000很保险
int n;
cin >> n;
while (n--) {
/*
x a0 a1
x b0 b1
*/
int a0, a1, b0, b1;
cin >> a0 >> a1 >> b0 >> b1;
fl = 0; // 多组数据,每次注意清零
int t = b1; // 拷贝出来,一直除到没有为止
// 枚举b1的每个质数小因子
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++;
f[fl++] = {p, s}; // 记录小质数因子和个数
}
}
// 如果存在大的质因子那么最多只有一个比如2*7=14中的7,此时t=7
// 也可能b1本身就是一个质数比如131,那么此时t=131
if (t > 1) f[fl++] = {t, 1}; // 记录到质数数组中
// 现在求出的是b1的所有质数因数题目要求的是约数,利用dfs通过质数因子获取所有约数
dl = 0; // 多组测试数据,也清一下零吧!
dfs(0, 1); // 一次dfs将质数因子数组 转换 约数数组,p的默认值是1
int res = 0; // 答案数量
for (int i = 0; i < dl; i++) { // 枚举所有约数
int x = d[i]; // 判断是不是符合题意
if (gcd(a0, x) == a1 && lcm(b0, x) == b1) res++;
}
// 输出结果
printf("%d\n", res);
}
return 0;
}