一.题目链接:
计蒜客 - T2094
二.题目大意:
已知 (a0, x) = a1, [b0, x] = b1
求满足上式 x 解的个数.
三.分析:
因为 [b0, x] = b1,所以 x 为 b1 的约数
又 b1 最多只有 10 个质因子,所以我们可以考虑 x 的质因子组成.
当前正在考虑质因子 p
设 m[0] 表示 a0 含 p 的个数,m[1] 表示 a1 含 p 的个数,
m[2] 表示 b0 含 p 的个数,m[3] 表示 b1 含 p 的个数,ans 表示 x 含 p 的个数.
若 m[0] < m[1], 则 ans 无解;若 m[0] == m[1], 则 ans >= m[1];若 m[0] > m[1], 则 ans == m[1].
若 m[2] < m[3], 则 ans == m[3];若 m[2] == m[3], 则 ans <= m[1];若 m[2] > m[3], 则 ans 无解.
因此只需打出素数表然后枚举素数即可.
注意:1. 如果 b1 % prime[i],应该 continue,因为 b1 最多只有 10 个不同的质因子,这样可以剪去绝大多数情况.
2. 枚举完所有素数后,若 b1 > 1,即 b1 是质数,应再计算 b1 因子的方案数.
四.代码实现:
#include <bits/stdc++.h>
using namespace std;
const int M = (int)45000;
int prime[M + 5], cnt;
bool is_prime[M + 5];
int a0, a1, b0, b1;
void get_prime()
{
cnt = 0;
memset(is_prime, 1, sizeof(is_prime));
is_prime[0] = is_prime[1] = 0;
for(int i = 1; i <= M; ++i)
{
if(is_prime[i]) prime[++cnt] = i;
for(int j = 1; j <= cnt && i * prime[j] <= M; ++j)
{
is_prime[i * prime[j]] = 1;
if(i % prime[j] == 0) break;
}
}
}
void divide(int& m, int& n, int p)
{
m = 0;
while(n % p == 0)
{
m++;
n /= p;
}
}
int work(int p)
{
int m[4], ans = 1;
divide(m[0], a0, p);
divide(m[1], a1, p);
divide(m[2], b0, p);
divide(m[3], b1, p);
if(m[0] == m[1] && m[2] == m[3] && m[1] <= m[3]) return m[3] - m[0] + 1;
else if(m[0] == m[1] && m[2] < m[3] && m[1] <= m[3]) return 1;
else if(m[0] > m[1] && m[2] < m[3] && m[1] == m[3]) return 1;
else if(m[0] > m[1] && m[2] == m[3] && m[1] <= m[3]) return 1;
else return 0;
}
int main()
{
get_prime();
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d %d %d %d", &a0, &a1, &b0, &b1);
int ans = 1;
for(int i = 1; i <= cnt && prime[i] <= b1; ++i)
{
if(b1 % prime[i]) continue;
if(!(ans *= work(prime[i]))) break;
}
if(b1 > 1) ans *= work(b1);
printf("%d\n", ans);
}
return 0;
}