2020牛客暑期多校訓練營(第三場)Fraction Construction Problem
阿新 • • 發佈:2020-07-21
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}\)
這一步判斷有沒有解,就是判斷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); } }