假设两只青蛙跳k次之后相遇,则需要满足:
x + km ≡ y + kn (mod L)
即 (x - y) + (m - n) * k ≡ 0 (mod L)
(x - y) = (n - m) * k + L * k'
最终就是求同余方程 ax + by = n的最小正整数解
数论中关于最大公约数有一个性质:存在整数x, y使gcd(a, b) = ax + by
所以若gcd(a, b) | n,则方程ax + by = n有解;否则无解
求同余方程解可使用扩展欧几里得算法
扩展欧几里得算法原理:
a * x0 + b * y0 = gcd(a, b)
b * x1 + (a % b) * y1 = gcd(b, a % b)
又gcd(a, b) = gcd(b, a % b)
则a * x0 + b * y0 = b * x1 + (a % b) * y1
由于a % b = a - a / b * b
所以 a * x0 + b * y0 = b * x1 + (a - a / b * b) * y1
x0 * a + y0 * b = y1 * a + (x1 - a / b * y1) * b
即x0 = y1,y0 = x1 - a / b * y1
最后一个问题就是怎么求出最小正整数解
假设求出的x0, y0为同余方程的一组解
则 a * x0 + b * y0 = n成立
又a * x + b * y = n
两式相减可得:a * (x - x0) + b * (y - y0) = 0
设d = gcd(a , b),上式两侧同时除以d可得:a / d * (x - x0) + b / d * (y - y0) = 0
此时gcd(a / d, b / d) = 1必然成立,所以
(b / d) | (x - x0) 即 x - x0 = (b / d) * t
最终 x = x0 + (b / d) * t
令r = b / d则
(x0 % r + r) % r 肯定能够找到[0, r)上的解
这篇blog解释的更加详细:http://www.cnblogs.com/comeon4mydream/archive/2011/07/18/2109060.html
#include <stdio.h>
long long gcd(long long m, long long n)
{
long long t;
while (n != 0)
{
t = m % n;
m = n;
n = t;
}
return m;
}
void gcd_ext(long long a, long long b, long long *px, long long *py)
{
long long t;
if (b == 0)
{
*px = 1;
*py = 0;
}
else
{
gcd_ext(b, a % b, px, py);
t = *py;
*py = *px - *py * (a / b);
*px = t;
}
}
int main(void)
{
long long x, y, m, n, l, d, s, t, r;
while (scanf("%lld %lld %lld %lld %lld", &x, &y, &m, &n, &l) != EOF)
{
d = x - y;
s = n - m;
t = gcd(s, l);
if (d % t != 0)
{
printf("Impossible\n");
}
else
{
r = l / t;
gcd_ext(s / t, l / t, &x, &y);
printf("%lld\n", ((x * (d / t) % r) + r) % r);
}
}
return 0;
}