题目大意:给你一个$a$,$b$表示$frac{a}{b}$,问你能否构造一个$frac{c}{d}-frac{e}{f}=frac{a}{b}$,如果能请输出c,d,e,f。否则输出-1 -1 -1 -1.要求$b>d,b>f,1<=c,e<=4e14$。
emmm,有三种情况:
第一种是分子分母不是最简,那么也就是说a,b存在一个公因子,同时也说明了b不是一个质数。那么我们可以直接构造$frac{a}{b}=frac{a+x}{b}-frac{x}{b}$,然后我们对分子分母同除以a,b的一个公因子,我们设为g,那么就会有$frac{a}{b}=frac{frac{a+x}{g}}{frac{b}{g}}-frac{frac{x}{g}}{frac{b}{g}}$,那么由于x是可以任意取的,那么我们为了方便,可以直接将其设为g,那么会得到$frac{a}{b}=frac{frac{a}{g}+1}{frac{b}{g}}-frac{1}{frac{b}{g}}$
第二种情况,分子分母最简了,但分母的不相同的质因子不超过一个,那么无解。如果分母不相同的质因子不超过一个,那么也就是说$b$可以表示为$p^k$,那么$frac{c}{d}-frac{e}{f}=frac{a}{p^k}$,最后化简的时候一定有$d'=p^{k_1},f'=p^{k_2}$,那么$d,f$一定包含因子$p^{s}$那么对于$cf,de$也一定包含因子$p^{ss}$,也就是说他们一定有公因子$p^m$。这就和分子分母最简相互矛盾了
第三种情况,分子分母最简了,但分母的不相同的质因子超过一个。那么一定有$df=b,gcd(d,f)=1$。那么我们只需要找到符合条件的$d,f$,然后带入到上面的式子就是$cf-ed=a$,那么可以看成$fx-dy=gcd(f,d)*a$。。。。这似乎就是拓展欧几里得了解决的问题了,拓展欧几里得不过关的话我也挺绝望的QAQ。。。
以下是AC代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int mac=2e6+10; int min_prim[mac],prim_num[mac]; int vis[mac]; void init() { int m=sqrt(mac); for (int i=2; i<m; i++){ if (!vis[i]){ min_prim[i]=i; for (int j=i*i; j<mac; j+=i){ vis[j]=1; if (!min_prim[j]) min_prim[j]=i;//找到每个数的最小质因子 } } } for (int i=1; i<mac; i++){ if (!vis[i]) continue; prim_num[i]++; int x=i; while (x%min_prim[i]==0) x/=min_prim[i]; if (x!=1) prim_num[i]++;//判断是否有两个互异的质因子 } } ll exgcd(ll a,ll b,ll &x,ll &y) { if (!b) { x=1; y=0; return a; } ll d=exgcd(b,a%b,y,x); y-=a/b*x; return d; } int main(int argc, char const *argv[]) { int t; init(); scanf ("%d",&t); while (t--){ int a,b; scanf ("%d%d",&a,&b); int g=__gcd(a,b); if (g!=1) { printf("%d %d %d %d ",a/g+1,b/g,1,b/g); continue; } if (prim_num[b]<=1) {printf("-1 -1 -1 -1 "); continue;} ll d=1,f=b; while (f%min_prim[b]==0) { f/=min_prim[b]; d*=min_prim[b]; } ll c,e; exgcd(f,d,c,e); e=-e; while (e<0 || c<0) e+=f,c+=d; printf ("%lld %lld %lld %lld ",1LL*c*a,d,1LL*e*a,f); } return 0; }