2020暑假牛客多校第三场F.Fraction Construction Problem(扩展欧几里得+因式分解)
题意:
思路:对原式化简得(c*f-d*e) / (d*f) = a/b。将a/b进行最简式化简得a1/b1
由此可知 c*f-d*e=a1 d*f=b1
分情况考虑,如果b1!=b 则可以令d=b1 f=1 c=a1+b1 e=1。
反之,因为b=c*f,要求c*f-d*e=a1,这很明显是个不定式,所以要令gcd(c,f)=1.所以要找出b的两个互质因子,如果没有则为-1 -1 -1 -1。
找到后用扩展欧几里得求解。
#include<bits/stdc++.h> using namespace std; typedef long long ll; int fun(int a,int b) { while(b) { int c=a%b; a=b; b=c; } return a; } void exgcd(ll a, ll b, ll& x, ll& y) { if (b == 0) { x = 1, y = 0; return; } exgcd(b, a % b, y, x); y -= a / b * x; } void pr(ll c, ll d, ll e, ll f) { ll d1 = __gcd(c, d), d2 = __gcd(e, f); printf("%lld %lld %lld %lld\n", c/d1, d/d1, e/d2, f/d2); } pair<int,int> v[2000010]; int main() { int t; scanf("%d",&t); while(t--) { int a,b; scanf("%d%d",&a,&b); int m=fun(a,b); if(m>1) { int d=b/m; int x=a/m; int c=x+1,e=1; cout<<c<<" "<<d<<" "<<e<<" "<<d<<endl; continue; } else { ll a1=1,a2=1,flag=0,tot=0; int bb=b; for(int i = 2; i*i <= bb; ++i) { if(bb % i == 0) { int c = 0; while(bb % i == 0) bb /= i, ++c; v[++tot] = make_pair(i, c); } } if(bb > 1) v[++tot] = make_pair(bb, 1); if(tot<=1) { flag=0; } else { flag=1; for(int i=1;i<=v[1].second;i++) a1*=v[1].first; a2=b/a1; } if(flag==0) { printf("-1 -1 -1 -1\n"); } else { ll x,y; exgcd(a2,a1,x,y); if(y > 0) { ll tmp = (y+a2-1)/a2; y -= tmp*a2, x += tmp*a1; } if(x < 0) { ll tmp = (-x+a1-1)/a1; y -= tmp*a2, x += tmp*a1; } x*=a; y*=a; if(x > 0 && y < 0) pr(x, a1, -y, a2); else puts("-1 -1 -1 -1"); } } } }