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;
}

 

posted @ 2020-08-06 22:19  杰瑞与汤姆  阅读(143)  评论(0编辑  收藏  举报