题目描述
Given a positive fraction p/q, you should find two positive integers a,b that p/q=a/b+b/a. If no such integers, report it.
输入描述:
The first line contains one integer T (1≤T≤10^5), denoting the number of test cases. For each test case: Input one line containing two integers p,q (1≤p,q≤10^7), denoting the given fraction.
输出描述:
For each test case: If solution exists, output one line containing two integers a,b (1≤a,b≤10^9), or print two zeros in one line if no solution.
输入
2 5 2 5 1
输出
1 2 0 0
题意: 给出p和q,求满足p / q = a / b + b / a的整数a和b,若不存在输出0 0。
分析: 这道题有两种解法,第一种是解方程的思想。将a / b看作整体x,可以把方程化简为x^2 - (p/q)*x + 1 = 0,先判断是否有解,若无解直接输出0 0,若有解需要判断解是否能表示为分数形式,解出一个解x = ((p/q)+根下Δ)/2,这里用任意一个解就行,另一个解就是1/x,要想x表示为分数,那么根下Δ一定是有理数,如果根下Δ无法开方就直接输出0 0,如果可以开方就通分一下得到答案。
另一种方法是枚举,这种方法比较好想,但是时间复杂度稍高一些。原方程化简得到p / q = (a^2+b^2) / (a*b),之后考虑a*b = k*q,a^2+b^2 = k*p,两等式同时成立时k的因子一定是平分给a和b,所以可以给a和b都除以根号k,这之后a和b仍然是整数,这说明若有解那一定存在a是q的某个因子,于是可以枚举q的所有因子。
具体代码如下:
解方程法:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#define ll long long
using namespace std;
signed main()
{
int T;
cin >> T;
while(T--)
{
ll p, q;
scanf("%lld%lld", &p, &q);
if(p*p < 4*q*q)
puts("0 0");
else if((ll)sqrt(p*p-4*q*q)*(ll)sqrt(p*p-4*q*q) != p*p-4*q*q)
puts("0 0");
else
printf("%lld %lld\n", p+(ll)sqrt(p*p-4*q*q), 2*q);
}
return 0;
}
枚举法:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#define ll long long
using namespace std;
signed main()
{
int T;
cin >> T;
while(T--)
{
ll p, q;
scanf("%lld%lld", &p, &q);
int t = __gcd(q, p);
p /= t, q /= t;
bool flag = false;
for(int a = 1; a*a <= q; a++)//枚举q的所有因子
{
if(q%a == 0)
{
int b = q/a;
if(p*a*b == q*a*a+q*b*b)
{
printf("%lld %lld\n", a, b);
flag = true;
break;
}
}
}
if(!flag)
puts("0 0");
}
return 0;
}