1. 程式人生 > >2016ACM/ICPC亞洲區大連站-重現賽 d

2016ACM/ICPC亞洲區大連站-重現賽 d

首先這道題需要理解一個概念

就是 若 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;
}