[POJ 1061]--青蛙的约会(扩展欧几里得)
青蛙的约会
|
Memory Limit: 10000K |
题目链接:http://poj.org/problem?id=1061
Description
我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设 青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你 求出它们跳了几次以后才会碰面。
Input
00000000,0 < m、n < 2000000000,0 < L < 2100000000。
Output
Sample Input
1 2 3 4 5
Sample Output
4
解题思路:首先把这道题转化为相关的数学方程:(n-m)t+pL=x-y,即二元一次不定方程at+bp=c,根据数论的相关定理,得知当c%gcd(a,b)==0时方程有整数解,
否则没有,即此题无解。
引用以下定理:
定理1 gcd(a,b)是ax+by的线性组合的最小正整数,x,y∈z;
定理2 如果ax+by=c,x,y∈z;则c%gcd==0;
定理3 如果a,b是互质的正整数,c是整数,且方程ax+by=c
(1)有一组整数解x0,y0则此方程的一切整数解可以表示为x=x0+bt;y=y0-at;t∈z;
(2)方程at+bp=c左右两边同除以gcd(a,b),得a1t+b1p=c1,再解最小正整数线性组合得一组解x1,y1,
则所求方程的一组解为T=x1*c1,P=y1*c1,根据(2)式可得t的最小正整数解为(T%b1+b1)%b1,此即为可行时所求解,
注意:因为所给数据比较大,这里全部用__int64。
代码如下:
1 #include <iostream> 2 using namespace std; 3 4 __int64 t, p; 5 __int64 get_gcd(__int64 a, __int64 b){ 6 return !b?a:get_gcd(b, a%b); 7 } 8 9 void extended_gcd(__int64 a, __int64 b){ 10 if (!b){ 11 t = 1; 12 p = 0; 13 } 14 else{ 15 __int64 temp; 16 extended_gcd(b, a%b); 17 temp = t - a / b*p; 18 t = p; 19 p = temp; 20 } 21 } 22 23 int main(){ 24 __int64 x, y, n, m, L, gcd; 25 cin >> x >> y >> m >> n >> L; 26 if (m == n){ 27 cout << "Impossible" << endl; 28 return 0; 29 } 30 __int64 a, b, c, c1; 31 a = n - m; 32 b = L; 33 c = x - y; 34 gcd = get_gcd(a, b); 35 c1 = c%gcd; 36 if (c1 != 0){ 37 cout << "Impossible" << endl; 38 return 0; 39 } 40 c /= gcd; 41 a /= gcd; 42 b /= gcd; 43 extended_gcd(a, b); 44 t *= c; 45 p *= c; 46 t = (t%b + b) % b; 47 cout << t << endl; 48 return 0; 49 }
当然也可以这么写:
d为n-m和L的最大公约数,x为(n-m)/d对L/d的逆元,即((n-m)/d) * x ≡ 1(mod L/d),即((n-m)/d) * x + (L / d)* y = 1的一组解,
所以((m-m)/d) * x + (L / d)* y = (x-y)/d的一组解为x0 = (x-y)/d * x.这也是(n - m) * x+ L * y = (x - y)的一组解。 (代码中cycle代表d)。
1 #include<iostream> 2 using namespace std; 3 long gcd(long a, long b){ 4 return !b ? a : gcd(b, a%b); 5 } 6 int main(){ 7 long x, y, m, n, L, i, cycle; 8 while (cin >> x >> y >> m >> n >> L){ 9 if (m > n) cycle = (y - x + L) % L; 10 else{ 11 cycle = (x - y + L) % L; 12 swap(m, n); 13 } 14 if (n == m || cycle%gcd(L, m - n)){ 15 cout << "Impossible" << endl; 16 continue; 17 } 18 for (i = 0;; i++){ 19 if ((i*L + cycle) % (m - n) == 0){ 20 cout << (i*L + cycle) / (m - n) << endl; 21 break; 22 } 23 } 24 } 25 return 0; 26 }