1. 程式人生 > >POJ-1061 青蛙的約會---擴展歐幾裏得算法

POJ-1061 青蛙的約會---擴展歐幾裏得算法

歐幾裏得 https clu cout 解題思路 什麽 不可 時間 正方

題目鏈接:

https://cn.vjudge.net/problem/POJ-1061

題目大意:

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

解題思路:

假設t時刻相遇

有:(x + mt) = (y + nt) (mod L)

也就是 x + mt - y - nt = K * L

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

(因為K取任意整數,移到方程左端可以不管他的正負,反正對求出的K不處理)

也就是:a * t + b * K = y - x   a = m - n b = L 求解t和K

特判 a = 0 的時候 x = y解為0,反之無解

當a < 0時,標記一下,然後a取正數,最後求出的t再取一下相反數即可

對於ax + by = c的求解

先求解ax + by = gcd(a, b) 求出x0,y0

如果gcd(x, y)整除c則有解,反之無解

根據x0 y0可得到一解:

x1 = x0 * c / gcd(a, b)

y1 = y0 * c / gcd(a, b)

所有解:

x = x1 + b / gcd(a, b) * t

y = y1 + a / gcd(a, b) * t

最小正數x的解

b` = b / gcd(a, b)

a` = a / gcd(a, b)

x2 = ((x1 % b`) + b`) % b`

y2 根據x2計算出來

同理可求出最小正數y的解

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4
using namespace std; 5 typedef long long ll; 6 ll extgcd(ll a, ll b, ll&x, ll&y)//ax+by = gcd(a, b)的解。返回值為gcd 7 { 8 ll d = a; 9 if(b) 10 { 11 d = extgcd(b, a % b, y, x); 12 y -= (a / b) * x; 13 } 14 else x = 1, y = 0; 15 return d; 16 } 17 int main() 18 { 19 ll x, y, m, n, l; 20 cin >> x >> y >> m >> n >> l; 21 ll xx, yy; 22 ll a = m - n, b = l; 23 if(a == 0) 24 { 25 if(x == y)cout<<"0"<<endl; 26 else cout<<"Impossible"<<endl; 27 return 0; 28 } 29 bool flag = 0; 30 if(a < 0)a = -a, flag = 1; 31 ll g = extgcd(a, b, xx, yy); 32 if((y - x) % g)cout<<"Impossible"<<endl; 33 else 34 { 35 xx = xx * (y - x) / g; 36 if(flag)xx = -xx; 37 l = l / g; 38 xx = ((xx % l) + l) % l; 39 cout<<xx<<endl; 40 } 41 return 0; 42 }

POJ-1061 青蛙的約會---擴展歐幾裏得算法