2020牛客暑期多校训练营(第三场)F.Fraction Construction Problem(数学)

F-Fraction Construction Problem

题意:给定a和b,构造 c d − e f = a b \dfrac{c}{d}-\dfrac{e}{f}=\dfrac{a}{b} dcfe=ba d , f < b d,fd,f<b
题解:
1.当ab不互质,即ab存在非1公因数时,可以构造出 a + x b − x b = a b \dfrac{a+x}{b}-\dfrac{x}{b}=\dfrac{a}{b} ba+xbx=ba ,x任取,因为要求 d , f < b d,fd,f<b,对等式左边分子分母同除ab的gcd即可(当然其他的非1公因数也可),设g为ab的gcd,构造的等式为 a g + 1 b g − 1 b g = a b \dfrac{\dfrac{a}{g}+1}{\dfrac{b}{g}}-\dfrac{1}{\dfrac{b}{g}}=\dfrac{a}{b} gbga+1gb1=ba
2.当ab互质,但b的互异质因子只有一个时,则无解。
    证明:b的互异质因子只有一个,即 b = p k b=p^k b=pk,上式通分后得到 c f − e d d f = a b \dfrac{cf-ed}{df}=\dfrac{a}{b} dfcfed=ba,则 d ′ = p k 1 , f ′ = p k 2 d'=p^{k_{1}},f'=p^{k_{2}} d=pk1,f=pk2,那么 d , f d,f d,f一定包含因子 p s p^{s} ps c f , e d cf,ed cf,ed也一定包含因子 p s p^{s} ps,则a一定包含因子 p s s p^{ss} pss,与ab互质矛盾

3.当ab互质,且b的互异质因子大于1个时,可令 d f = b df=b df=b,找到一组互质的 d , f d,f d,f带入上式, c f − e d = a = > f x − d y = g c d ( f , d ) ∗ a cf-ed=a =>fx-dy=gcd(f,d)*a cfed=a=>fxdy=gcd(f,d)a,拓展欧几里得找一组可行解即可,注意找到的 x , y x,y x,y可能为负,换一下即可

b = 1 b=1 b=1或b为质数时,一定无解,可以用线性筛先将质数筛出来,提高效率。b的范围是2e6,我看成了1e6,没筛完,导致一直wa(自抠双目)

Code:

#include 
using namespace std;
#define ll long long
#define db double
#define ull unsigned ll
#define pii pair
#define pdd pair
#define pll pair
#define mem(a, b) memset(a, b, sizeof(a));
#define lowbit(x) (x & -x)
#define lrt nl, mid, rt << 1
#define rrt mid + 1, nr, rt << 1 | 1
template <typename T>
inline void read(T& t) {
    t = 0;
    int f = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        t = t * 10 + ch - '0';
        ch = getchar();
    }
    t *= f;
}
const int dx[] = {0, 1, 0, -1};
const int dy[] = {1, 0, -1, 0};
const ll Inf = 0x7f7f7f7f7f7f7f7f;
const int inf = 0x7f7f7f7f;
const db eps = 1e-5;
const db Pi = acos(-1);
const int maxn = 2e6 + 10;

int cnt;
bool is_prime[maxn];
int primes[maxn];

void Primes(int n) {
    memset(is_prime, true, sizeof(is_prime));
    is_prime[1] = 0;
    for (int i = 2; i <= n; i++) {
        if (is_prime[i])
            primes[++cnt] = i;
        for (int j = 1; j <= cnt && i * primes[j] <= n; j++) {
            is_prime[i * primes[j]] = 0;
            if (i % primes[j] == 0)
                break;
        }
    }
}

void exgcd(ll a, ll b, ll& x, ll& y) {
    if (!b) {
        y = 0, x = 1;
        return;
    }
    exgcd(b, a % b, y, x);
    y -= a / b * x;
}

int main(void) {
    Primes(2e6);
    int T;
    read(T);
    while (T--) {
        ll a, b, c, d, e, f, k;
        read(a), read(b);
        if (__gcd(a, b) != 1) {
            ll k = __gcd(a, b);
            printf("%lld %lld 1 %lld\n", a / k + 1, b / k, b / k);
            continue;
        }
        if (b == 1 || is_prime[b]) {
            printf("-1 -1 -1 -1\n");
            continue;
        }
        ll tmp = b, op = 1;
        for (int i = 1; primes[i] * primes[i] <= tmp; i++) {
            if (tmp % primes[i] == 0) {
                while (tmp % primes[i] == 0)
                    tmp /= primes[i], op *= primes[i];
                break;
            }
        }
        if (tmp == 1) {
            printf("-1 -1 -1 -1\n");
            continue;
        }
        d = tmp, f = op;
        ll x, y;
        exgcd(f, d, x, y);
        c = x * a, e = y * a;
        if (c < 0 && e > 0)
            printf("%lld %lld %lld %lld\n", e, f, -c, d);
        else
            printf("%lld %lld %lld %lld\n", c, d, -e, f);
    }
    return 0;
}

你可能感兴趣的:(数学,牛客多校)