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; }
收集牛客暑期多校训练营的题解