1. 程式人生 > >POJ-1061 青蛙的約會(擴充套件歐幾里德)

POJ-1061 青蛙的約會(擴充套件歐幾里德)

                                                             青蛙的約會

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 130016 Accepted: 28506

Description

兩隻青蛙在網上相識了,它們聊得很開心,於是覺得很有必要見一面。它們很高興地發現它們住在同一條緯度線上,於是它們約定各自朝西跳,直到碰面為止。可是它們出發之前忘記了一件很重要的事情,既沒有問清楚對方的特徵,也沒有約定見面的具體位置。不過青蛙們都是很樂觀的,它們覺得只要一直朝著某個方向跳下去,總能碰到對方的。但是除非這兩隻青蛙在同一時間跳到同一點上,不然是永遠都不可能碰面的。為了幫助這兩隻樂觀的青蛙,你被要求寫一個程式來判斷這兩隻青蛙是否能夠碰面,會在什麼時候碰面。  我們把這兩隻青蛙分別叫做青蛙A和青蛙B,並且規定緯度線上東經0度處為原點,由東往西為正方向,單位長度1米,這樣我們就得到了一條首尾相接的數軸。設青蛙A的出發點座標是x,青蛙B的出發點座標是y。青蛙A一次能跳m米,青蛙B一次能跳n米,兩隻青蛙跳一次所花費的時間相同。緯度線總長L米。現在要你求出它們跳了幾次以後才會碰面。 

Input

輸入只包括一行5個整數x,y,m,n,L,其中x≠y < 2000000000,0 < m、n < 2000000000,0 < L < 2100000000。

Output

輸出碰面所需要的跳躍次數,如果永遠不可能碰面則輸出一行"Impossible"

Sample Input

1 2 3 4 5

Sample Output

4

題意:

有青蛙A,青蛙B兩隻,他們分別從x,y為起點出發,沿著圓圈的相同方向走,圓的長度為L,青蛙A的速度為m,青蛙B的速度為n,問你需要跳多少次它兩個會相遇。

思路:

設時間為t,青蛙A現在的位置為(x+m*t)% L,青蛙B現在的位置為(y+n*t)% L,他兩個相遇即(x+m*t)% L == (y+n*t) % L 

(n-m)*t + k*L =  x - y;

a = n-m

b = L;

c = x-y;

滿足a*x+b*y = c表示式,然後通過擴充套件歐幾里德模板求出一組(x,y),然後通過通解找最小正整數x,就是我們要輸出的答案。

x0 = x0 % (b/d) + (b/d);就可以求出最小非負整數解x了!

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b, ll &x, ll &y)
{
	if(a == 0 && b == 0)
		return -1;
	if(b == 0) {
		x = 1; y = 0; return a;
	}	
	ll d = gcd(b,a%b,y,x);
	y -= a / b * x;
	return d;
}
int main()
{	
	ll x, y, m, n, l;
	cin >> x >> y >> m >> n >> l;
	ll a = n-m;
	ll b = l;
	ll c = x-y;
	ll x0, y0;
	ll d = gcd( a, b, x0, y0);
	if(c % d)
		cout << "Impossible" << endl;
	else {   
		x0 = x0*c/d;
		y0 = y0*c/d;
		int t = b / d;  
		if(x0 >= 0)	 //	求x的最小正整數 
			x0 = x0 % t;
		else
			x0 = x0 % t + t;  
		cout << x0 << endl;
	}	
	return 0; 
}