牛客2020多校第三场 F.Fraction Construction Problem
F.Fraction Construction Problem
https://ac.nowcoder.com/acm/contest/5668/F
分析:
1.a,b不互质,因为题目要求d<b,f<b,所以只要gcd(a,b)=g!=1,分母就可以直接写成b/g的形式,只要再构造一下式子,如a/g+1,b/g,1,b/g就是一组答案。
2.在b的因数里面找一对d,f互质却d*f=b。找不到则无解,找到了可以通分把式子化成f * c -d * e=a,然后就变成exgcd的形式(c,-e是未知数)。求得c',e'的解后,由exgcd通解c=c' * a +b/gcd(a,b) * k,e=e' * a -a/gcd(a,b) * k,这时可以令k=0,得到答案就是c' * a,e' * a。要注意因为求得的e'一定是负的,c'可能是负的,为保证c'是正数,可以让c'一直+d,e'一直+f。因为在原式中,(c+k * d)/d - (e+k * f)/f=a/b,k任取。
3.证明为什么找不到一对互质且d*f=b就是无解?
如果d,f不互质,即f=k*d,式子可化为(k * c-e)/f=a/b,因为f<b,且a,b互质,所以a/b已经是最简形式,而f<b,使得左式不可能等于右式。
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<sstream> #include<vector> #include<stack> #include<deque> #include<cmath> #include<map> #include<queue> #include<bitset> #define sd(x) scanf("%d",&x) #define ms(x,y) memset(x,y,sizeof x) #define fu(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) #define all(a) a.begin(),a.end() using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn=2e6+79; const int mod=1e9+7; const ll INF=1e18+7; vector<int> cob; int gcd(int a,int b) { if(a<b) swap(a,b); if(b==0) return a; return gcd(b,a%b); } void depart(int b) { cob.clear(); for(int i=2;i*i<=b;i++) { if(b%i==0) { if(gcd(i,b/i)==1) { cob.push_back(i); break; } //找到一对互质的 } } } ll exgcd(ll a,ll b,ll &x,ll &y) { ll d=a; if(b!=0) { d=exgcd(b,a%b,y,x); y-=(a/b)*x; } else { x=1,y=0; } return d; } int main() { int T; cin>>T; while(T--) { int a,b,g; sd(a);sd(b); ll c,d,e,f; if((g=gcd(a,b))!=1) { c=a/g+1,d=b/g,e=1,f=b/g; } else { depart(b); if(cob.size()>=1) { d=cob[0],f=b/d; exgcd(f,d,c,e); e=-e; while(c<=0||e<=0) c+=d,e+=f; c*=a; e*=a; } else c=d=e=f=-1; } printf("%lld %lld %lld %lld\n",c,d,e,f); } return 0; }