POJ1061 青蛙的約會

題目來源:http://poj.org/problem?id=1061html

題目大意:ios

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

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

輸出:輸出碰面所須要的跳躍次數,若是永遠不可能碰面則輸出一行"Impossible"spa


Sample Inputcode

1 2 3 4 5

Sample Outputhtm

4

終於有一道中文題目了,真是淚流滿面T^T..blog

  由題意知,實際上問題是要求解下面的方程:  ci

      (1)get

  其中 t 爲未知數,要求的是 t 的非負最小值。上式可變形爲: (2)

  其中 t 和 k 爲未知數。再將上式簡化爲(3) 的形式。其中, a b c 均爲整數常數。數論中的相關理論(具體什麼理論我也不知道=。=)保證了:當 c = gcd(a, b)時,該方程的 t 和 k 必定有解。因此若是能夠把(2)式轉化爲 (4) 的形式,則原問題有解,不然無解,應輸出「Impossible.」。

  接下來講明(4)式的解法--擴展的歐幾里得算法

  首先請移步這裏回顧一下求兩數最大公約數的樸素歐幾里得算法。而後, 咱們把代碼搬過來:

int gcd(int a, int b) {
    if(b == 0)
        return a;
    return gcd(b, a % b);
}

  所謂的擴展歐幾里得算法,代碼以下:

int x, y;

int
ex_gcd(int a, int b) { if (b == 0) { x = 1; y = 0; return a; } else { int r = ex_gcd(b, a % b); int t = x; x = y; y = t - a / b * y; return r; } }

這裏的a, b與前面方程(4)裏的a, b對應, x, y對應t, k,返回值爲gcd(a, b)。[ax + by = gcd(a, b)]. 咱們發現,ex_gcd算法與gcd相比,多了 x 與 y 的賦值過程。只要在紙上演算一下,會發現其實算法很好理解:

1. b == 0 時,對應方程 gcd(a, b) = a, 對應的原方程爲:ax + 0y = a, 因此能夠賦值 x = 1, y = 0;

2. 當 b != 0 時,由於gcd(a, b) = gcd(b, a % b). 因此存在x'和y'知足:

  ax + by = gcd(a, b)

       = gcd(b, a % b)

       = bx' + (a % b)y'

       = bx' + (a - a / b * b)y'

       = ay' + b(x' - a / b * y')

因而咱們從上面連等式中能夠找到對應關係:x = y'; y = x' - a / b * y'. 算法就是利用該遞推關係就求出方程(4)的一組解,設之爲(x0, y0)。

顯然解不是惟一的,而是應該構成一組解系。設gcd(a, b) = d, 則 ax0 + by0 = d, 且有:

  

因而咱們構造出瞭解系: 其中n爲任意整數。

而後對於通常形式的方程 ax + by = c, 則對應着解系. 因此若是 c/gcd(a, b) 是整數,則該方程有整數解,若不是則無整數解。

那麼回到題目中,本題實際上求的是知足方程的x中的最小非負值,求得了x0和d後應該是不可貴到了。至此應該把原理講清楚了吧,嗯,上AC代碼。            

 1 ////////////////////////////////////////////////////////////////
 2 //        POJ1061 Frogs' Dating
 3 //        Memory: 216K        Time: 0MS
 4 //        Language: C++        Result : Accepted
 5 ////////////////////////////////////////////////////////////////
 6 
 7 #include <iostream>
 8 
 9 using namespace std;
10 
11 long long x, y;
12 
13 long long ex_gcd(long long a, long long b) {
14     if (b == 0) {
15         x = 1;
16         y = 0;
17         return a;
18     } else {
19         long long r = ex_gcd(b, a % b);
20         long long t = x;
21         x = y;
22         y = t - a / b * y;
23         return r;
24     }
25 }
26 
27 int main(void) {
28     long long X, Y, m, n, L, c, d, t;
29     cin >> X >> Y >> m >> n >> L;
30     c = X - Y;
31     d = ex_gcd(n - m, L);
32     t = c % d;
33     if (t == 0) {
34         long long k = c / d;
35         x *= k;
36         t = d * x / L;
37         x -= t * L / d;
38         if (x < 0) {
39             x += L / d;
40         }
41         cout << x << endl;
42     } else {
43         cout << "Impossible" << endl;
44     }
45     return 0;
46 }
View Code

關於求知足條件的最小非負數的附加解釋:

  令 ,此時求得的n對應着最接近0的x,若是算出的x小於0,則在它的基礎上再加一個週期 b/d 便可。

相關文章
相關標籤/搜索