2020牛客暑期多校训练营(第三场)F

Fraction Construction Problem

https://ac.nowcoder.com/acm/contest/5668/F

题目描述

  There are queries.
  In each query, you are given two positive integers and .
  Please print a line consists of four positive integers c,d,e,f satisfying the following constraints: , and , .
  If there are multiple solutions, you can print anyone.
  If there are no solution, please print -1 -1 -1 -1 in this line.

输入描述

  The first line contains one integer , the number of test cases.
  The only line of each test case contains two integers and .

输出描述

  For each test case print four integers . If there are no solution, should all be .

示例1

输入

3
4 1
1 6
37 111

输出

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

分析

  若 ,代表分数 可以约分为 。简便起见,直接令 ,那么就有 ,有一组解为
  若 ,那么 已经是最简分式,将等式左边通分后,可得 。首先,当 为质数的幂时,无解(文末给出证明)。接下来考虑 有多个不相同质因子的情况。根据算数基本定理,可以将 写成有限个质数的乘积,。方便起见,直接令 是一个裴蜀方程,当且仅当 时方程有整数解。若能构造得到的 使得 ,那么方程一定有整数解。显然这样的构造方案是存在的,令 ,就有 。可以用扩展欧几里得算法求得 的特解 ,为了满足条件 ,不妨让 尽量向 靠近。令 ,求一个不等式组即可得到 的上界。有不等式组 ,解得
  接下来给出证明:当 为质数的幂次时,无解。
  设 。由于 是质数的幂次,可设 ,其中 。那么有 。很显然, 式的左边分式可以上下同除以 进行约分;又 ,故 ,这样一来, 就是一个可约分的分式,与事实矛盾。证毕。

代码

/******************************************************************
Copyright: 11D_Beyonder All Rights Reserved
Author: 11D_Beyonder
Problem ID: 2020牛客暑期多校训练营(第三场)Problem F
Date: 8/15/2020
Description: Number Theory, Construction, Extend Euclid Algorithm
*******************************************************************/
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
const ll top=4000000000000;
void ex_gcd(ll,ll,ll&,ll&);//扩展欧几里得算法
vector<int> divide(int);//分解质因数
int main(){
    int _;
    for(cin>>_;_;_--){
        int a,b;
        ll c,d,e,f;
        scanf("%d%d",&a,&b);
        int gcd=__gcd(a,b);
        if(gcd==1){
                        //互质
            vector<int>prime_factor=divide(b);
            if(prime_factor.size()<=1){
                                //只有一种质因子
                puts("-1 -1 -1 -1");
            }else{
                ll p=1;
                while(b%p==0){
                    p=p*prime_factor.front();
                }
                p/=prime_factor.front();
                d=p;
                f=b/p;
                ex_gcd(f,d,c,e);
                c=c*a;
                e=-e*a;
                                //解不等式
                ll k=min((top-c)/d,(top-e)/f);
                c+=k*d;
                e+=k*f;
                printf("%lld %lld %lld %lld\n",c,d,e,f);
            }
        }else{
            d=f=b/gcd;
            e=1;
            c=a/gcd+1;
            printf("%lld %lld %lld %lld\n",c,d,e,f);
        }
    }
    return 0;
}
void ex_gcd(ll a,ll b,ll& x,ll& y){
    if(!b){
        x=1;
        y=0;
        return;
    }else{
        ex_gcd(b,a%b,x,y);
        ll temp=x;
        x=y;
        y=temp-a/b*y;
    }
}
vector<int> divide(int x){
    vector<int>prime_factor;
    for(register int i=2;i*i<=x;i++){
        if(x%i==0){
            prime_factor.push_back(i);
            while(x%i==0) x/=i;
        }
    }
    if(x>1) prime_factor.push_back(x);
    return prime_factor;
}
牛客暑期多校训练营题解 文章被收录于专栏

收集牛客暑期多校训练营的题解

全部评论

相关推荐

点赞 评论 收藏
分享
头像
11-21 11:39
四川大学 Java
是红鸢啊:忘了还没结束,还有字节的5k 违约金
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务