P1072 Hankson 的趣味题
数论永远不会系列。。。
这道题显然可以打暴力的50pts,算一下时间范围内能枚举的最大x即可。
满分做法建立在优化暴力。。。
题目中给了我们两个东西:
-
\(x\)和\(a_0\)的最大公约数是\(a_1\)
-
\(x\)和\(b_0\)的最小公倍数是\(b_1\)
可以化为两个式子:
\[gcd(x, a_0)=a_1和x \times b_0 = b_1 \times gcd(x, b_0)
\]
显然可以化为:
\[gcd(\frac{x}{a_1}, \frac{a_0}{a_1})=1和gcd(\frac{b_1}{b_0}, \frac{b_1}{x})=1
\]
那么可以得到:\(x\)必须是\(a_1\)的倍数,且\(x\)必须是\(b_1\)的因数。
所以我们可以\(O(\sqrt{b_1})\)地枚举\(b_1\)的所有因数,然后同时满足以上所有关系的\(x\)就是答案。
PS:\(O(\sqrt{b_1})\)地枚举因数的时候,我们记得去求出另一个因数出来!
也要记得对另一个因数一视同仁!不要当前因数不满足条件就不判断另一个因数了!
代码:
#include<cstdio>
#include<cmath>
#define ll long long
ll n, a0, a1, b0, b1;
ll gcd(ll a, ll b)
{
return b == 0 ? a : gcd(b, a % b);
}
int main()
{
scanf("%lld", &n);
for(int i = 1; i <= n; i++)
{
scanf("%lld%lld%lld%lld", &a0, &a1, &b0, &b1);
ll ans = 0;
for(int x = 1; x * x <= b1; x++)
{
if(b1 % x == 0)
{
ll other = b1 / x;
if(x % a1 == 0 && gcd(x / a1, a0 / a1) == 1 && gcd(b1 / b0, b1 / x) == 1) ans++;
if(x == other) continue;
if(other % a1 == 0 && gcd(other / a1, a0 / a1) == 1 && gcd(b1 / b0, b1 / other) == 1) ans++;
}
}
printf("%lld\n", ans);
}
return 0;
}