2020牛客多校第三场F题Fraction Construction Problem(扩展欧几里得数论)
题目链接:https://ac.nowcoder.com/acm/contest/5668/F
题意:输入a,b构造分数等式成立
题解:分类讨论
第一种是分子分母不是最简,那么也就是说a,b存在一个公因子,同时也说明了b不是一个质数。
第二种情况,分子分母最简了,但分母b的不相同的质因子不超过一个,那么无解。无法分解b
第三种情况,分子分母最简了,但分母的不相同的质因子超过一个。扩展欧几里得。
#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\n",a/g+1,b/g,1,b/g); continue; } if (prim_num[b]<=1) {printf("-1 -1 -1 -1\n"); 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\n",1LL*c*a,d,1LL*e*a,f); } return 0; }