2020牛客暑期多校第三场 F - Fraction Construction Problem(扩欧+最小质因子)

传送门


分情况讨论:

  • g c d ( a , b ) > 1 gcd(a,b)>1 ,因为最简分数的唯一性,那么我们可以令 d = b / g c d ( a . b ) , f = e = 1 d=b/gcd(a.b),f=e=1 ,那么可以解出 c = a / g c d ( a , b ) + b / g c d ( a , b ) c=a/gcd(a,b)+b/gcd(a,b)
  • g c d ( a , b ) = 1 gcd(a,b)=1 ,因为 d , f < b d,f<b ,显然不能令其中一个为 1 1 ,那么此时我们考虑将 b b 分解为互质的两部分并且分别赋值给 d , f d,f ,怎么分实际上都可以,但是为了方便我们将 b b 分为最小质因子和另外一部分(如果最小质因子为它本身那么无解)然后代入可以得到方程 a = c f d e a=cf-de ,然后使用 e x g c d exgcd 求解 c f d e = 1 cf-de=1 方程即可,但是我们需要注意,求出来的 e e 一定是负数,但是不能保证 c c 是非负,因为只是最小整数解,那么就不断加上各自的系数直到均为正数,最后再都乘以 a a
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define lowbit(x) (x&(-x))
#define mkp(x,y) make_pair(x,y)
#define mem(a,x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const double dinf=1e300;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=2e6+10;

int prime[maxn/3],fac[maxn];
int cnt;

ll gcd(ll a,ll b){
    return b==0?a:gcd(b,a%b);
}

ll exgcd(ll a,ll b,ll &x,ll &y){
    if(!b){
        x=1,y=0;
        return a;
    }
    ll g=exgcd(b,a%b,y,x);
    y-=(a/b)*x;
    return g;
}

void euler(){
    int t;
    fac[1]=1;
    for(int i=2;i<maxn;i++){
        if(!fac[i]){
            prime[cnt++]=i;
            fac[i]=i;
        }
        for(int j=0;(t=i*prime[j])<maxn;j++){
            fac[t]=prime[j];
            if(!(i%prime[j])) break;
        }
    }
}

int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    //ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    ll a,b,c,d,e,f;
    int t;
    euler();
    scanf("%d",&t);
    while(t--){
        scanf("%lld%lld",&a,&b);
        ll p=gcd(a,b);
        if(p>1){
            a/=p,b/=p;
            d=b,f=e=1LL,c=a+b;
            printf("%lld %lld %lld %lld\n",c,d,e,f);
        }else{
            d=1,f=b;
            while(fac[b]!=1 && f%fac[b]==0){
                d*=fac[b];
                f/=fac[b];
            }
            if(b==d || f==1){
                puts("-1 -1 -1 -1");
            }else{
                exgcd(f,d,c,e);
                e=-e;
                while(e<=0 || c<=0){
                    e+=f;
                    c+=d;
                }
                e*=a,c*=a;
                printf("%lld %lld %lld %lld\n",c,d,e,f);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44691917/article/details/107497357