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;
}
posted @ 2018-10-22 22:01  Garen-Wang  阅读(135)  评论(0编辑  收藏  举报