1. 程式人生 > 實用技巧 >2020牛客暑期多校訓練營(第三場)Fraction Construction Problem

2020牛客暑期多校訓練營(第三場)Fraction Construction Problem

2020牛客暑期多校訓練營(第三場)Fraction Construction Problem

題解:

\(g = gcd(a,b)\)

  • \(b==1\) 無解

  • 首先分析 \(g!=1\) ,那麼就很簡單了,\(e=0,f=b-1\)\(c=a/g,d=b/g\)

  • 然後再分析 \(g==1\) ,對題目給出的式子化簡,

    \(\frac{c}{d}-\frac{e}{f}=\frac{cf-ed}{df}=\frac{a}{b}\) ,上面的式子很像 \(ax+by=gcd(a,b)\) (這個是別人告訴我的) ,所以呢 上式就可以變成 \(gcd(f,d)*x\) ,所以化簡之後的式子就是 :\(\frac{x}{lcm(d,f)}=\frac{a}{b}\)

    ,因為 \(gcd(a,b)=1\) ,所以 \(lcm(d,f)=b\) ,所以 \(x=a\) ,最後我們可以讓 \(gcd(d,f)=1\)\(lcm(d,f)=b\)

    這一步判斷有沒有解,就是判斷b是否有兩個不同的素因子,如果有就有解,否則就無解。

  • 最後要注意的是把擴充套件歐幾里得的答案轉化成正數。

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e3+10;
typedef long long ll;
ll gcd(ll a,ll b) {
    return b == 0 ? a : gcd(b, a % b);
}
int isp[maxn],cnt,v[maxn];
void init() {
    cnt = 0;
    memset(v,0,sizeof(v));
    for (int i = 2; i < maxn; ++i) {
        if (!v[i]) {
            v[i] = i;
            isp[cnt++] = i;
        }
        for (int j = 0; j < cnt; ++j) {
            if (1ll * i * isp[j] >= maxn) break;
            v[i * isp[j]] = isp[j];
        }
    }
}
long long extend_gcd(long long a, long long b, long long &x, long long &y) {
    if (a == 0 && b == 0) return -1;
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    long long d = extend_gcd(b, a%b, y, x);
    y -= a / b * x;
    return d;
}
int main() {
    int t;
    init();
    scanf("%d", &t);
    while (t--) {
        ll a, b;
        scanf("%lld%lld", &a, &b);
        if (b == 1) {
            printf("-1 -1 -1 -1\n");
            continue;
        }
        ll g = gcd(a, b);
        if (g != 1) {
            printf("%lld %lld %d %lld\n", a / g + 1, b / g, 1, b / g);
            continue;
        }
        ll d = b;
        for (int i = 0; i < cnt; i++) {
            while (d % isp[i] == 0) d /= isp[i];
            if (d != b) break;
        }
        ll f = b / d;
        if (d == 1 || f == 1) {
            printf("-1 -1 -1 -1\n");
            continue;
        }
        ll c = 0,e = 0;
        ll ans=extend_gcd(f,d,c,e);
        c=(c%d+d)%d;
        e=-(1-c*f)/d;
//        printf("c=%lld e=%lld f=%lld d=%lld ans=%lld\n",c,e,f,d,ans);
        c = c*a,e=e*a;
        printf("%lld %lld %lld %lld\n",c,d,e,f);
    }
}