2020牛客暑期多校训练营Fraction Construction Problem(扩展欧几里得)

本文介绍了如何利用扩展欧几里得算法解决Fraction Construction Problem。当a和b互质时,需要找到b的两个互质因子来满足等式。如果b无法分解为互质因子或a和b不互质,则可能出现无解的情况。文章提供了无解的特判条件和解题代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Fraction Construction Problem

题目描述

在这里插入图片描述

输入描述:

在这里插入图片描述

输出描述:

在这里插入图片描述

示例1

输入

3
4 1
1 6
37 111

输出

-1 -1 -1 -1
1 2 1 3
145 87 104 78

题目大意

对于整式在这里插入图片描述
给定a,b的值,求任意一组c,d,e,f的值使得等式成立。
无解则输出-1-1-1-1。

分析

在这里插入图片描述
首先看这个式子,在d*f==b时可以化成这样,一拍脑瓜想到可以用扩欧解方程。

所以我们只要把b分解成d*f,并且满足gcd(d,f)=1,这样就可以使构造成立(通分的知识,学前班的),然后一套模板解方程。于是我们凑出了一组答案。

有的童鞋想,那那那我d和f其中一个为1不就可以了。
嗯没错,可是题目中说了,d和f均小于b(不然不是水题了?),所以我们需要找出b的两个互质因子。
但是如果a和b不是互质的,那就一约分后d或f就可以取1了。所以这种情况可以直接特判掉,即方便又省时(非常的nice)。

无解

但是也有可能他找不到一对互质因子,那就是无解了。比如b=81,它不能分解成互质因子。除此以外,b=1或b是质数当然也是无解的情况。
(无解判断方式有很多,自行选择)

综述

1、gcd(a,b)!=1,直接使d(或f)=0,出答案,简洁明了。
2、gcd(a,b)=1&&(prime(b)||b无法拆成互质数之积||b=1),则无解,畅快淋漓,速战速决。
3、其他有解情况,则用扩欧解方程,然后通过解的正负判断对应。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=2e6+10;
int gcd(int a,int b){return a%b==0?b:gcd(b,a%b);}//听+说ll会TLE,果然。
ll exgcd(ll a,ll b,ll &x,ll &y){
    if(b==0){x=1;y=0;return a;}
    ll c=exgcd(b,a%b,y,x);
    y-=a/b*x;return c;
}//扩欧
int main()
{
    int t,a,b,r;
    for(scanf("%d",&t);t--;){//学习dalao的新操作
        scanf("%d%d",&a,&b);
        if(b==1){puts("-1 -1 -1 -1");continue;}//b是1不要再继续了,省时。
        r=gcd(a,b);
        if(r!=1){
            printf("%d %d %d %d\n",a/r+b/r,b/r,b/r,b/r);
            continue;
        }//ab不互质直接出答案
        ll x,y;
        int d=1,f=b;
        for(d=2;d*d<=b;d++)
            if(b%d==0&&gcd(d,b/d)==1){
                d*=1ll,f=1ll*b/d;break;
            }//穷举法求素因子,也可以用类筛法。
        if(f==b){puts("-1 -1 -1 -1");continue;}//找不到合法的分解,素数也包含在内。
        r=exgcd(f,d,x,y);//解方程
        x=x*1ll*a;y=y*1ll*a;//扩欧基本操作--求通解
        if(x>0&&y<0)
            printf("%lld %d %lld %d\n",x,d,-y,f);
        else
            printf("%lld %d %lld %d\n",y,f,-x,d);
        //根据正负判断对应
    }
}

END

有错即评。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值