首先这道题需要理解一个概念
就是 若 i,j 互质 ,则 i+j 和 i*j 互质
证明如下:(感谢队友的思路)
如果 i j 互质, i+j 和 i*j 不互质,那么 i+j 和 i*j 存在公因数 T ,那么由题意可知 ,T必定为 i 或 j 的因数,同时 T 还为 i + j 的因数,那么假设 i % t == 0, ( i + j ) % t == 0, j 必定为 t 的一个倍数,满足不了i j 互质,故猜想成立。
(证明不严谨。。。有漏洞望大佬们指出)
题干很简单
A = X+Y , B= GMD(X,Y) 求 x 最小时的 X Y ,无解输出 No Solition
然后先去看本题 A = X+Y , B = GMD(X,Y) 那么有已知的最小公倍数和最大公约数关系可知
B * GCD(X,Y) = X*Y
看到 X*Y已知,X+Y已知,求X Y,很不由自主的就想到了韦达定理。。
那么根据韦达定理 (设 gcd(x,y) = k)
X+Y = A
X-Y = sqrt( A*A - 4*k*B)
所以整个问题的难点之一就在于 如何把 k 变成已知量
那么就开始运用我们开头用到的定理。
(i+j) / k = A / k;
( i*j ) / k = B / k;
因为 i/k 和 j/k 互质 那么 i/k + j/k 和 i/k * j/k 互质,则有 A/k 和 B/k 互质
那么 k 也就等于 gcd( A, B )
所以这道题也就出来答案了,但是注意,当根号下的数 小于0时 无解,得出的结果不是整数的时候 也是无解(题里说了是整数)
以下为AC 代码
#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
#define ll long long int
ll gcd(ll a,ll b)
{
if(a%b)
return gcd(b,a%b);
return b;
}
ll max(ll a, ll b)
{
if(a>b)
return a;
else
return b;
}
ll min(ll a, ll b)
{
if(a>b)
return b;
else
return a;
}
ll a,b;
ll x,y;
int main()
{
while(~scanf("%lld%lld",&a,&b))
{
ll k=gcd(a,b);
ll d = a*a-4*b*k;
ll dd =(ll)sqrt(1.0*d);
if(d<0)
{
printf("No Solution\n");
continue;
}
else if((dd+a)%2!=0||dd*dd!=d)
{
printf("No Solution\n");
continue;
}
else
{
x = (a + dd) / 2;
y = a - x;
printf("%lld %lld\n",min(x,y),max(x,y));
}
}
return 0;
}