大意不再赘述。
思路:看过奥运会跑步比赛的都知道,一人在前,一人在后,两个人可以相遇的话,要么一个人可以追上另一个人,要么一个人落后另一个人n圈。
反之,不能相遇的话,在题目中的理解就是,一个人不能永远超过另一个人n圈或者是速度相等(ax一定不等于by)。
在这题中,我们以纬度的长度L为参照物,如果青蛙A在时间T可以相遇青蛙B的话,那么有x + m*T - y - n*T = p*L或者是 y + n*T - x - m*T = pL; p∈Z。
如何去求解这个方程呢?我们可以把未知数放一边,已知数放一边,即:(n-m)*T - p*L = x-y ①
有了这个方程,我们就可以把(n-m)看做已知数a,L看做已知数b, 即求解方程:a*T - p*b = c;②
注意,我们最终的目的是求T。这个方程我们也不好求解,于是再变为:a*T - p*b = gcd(a, b);③
求解③方程我们可以通过扩展欧几里得算法来求解,我们可以求出一组解(T0, p0)满足③方程的值,如果要求最小的一组(T,p)的值得话,我们可以这样去写:
T *= (ax-by)/d;
T = (T%b1+b1)%b1;
为什么可以这样?介绍两个引理:
1、设a, b, c为任意整数。若方程ax+by = c的一组整数解为(x0,y0),则它的任意整数解都可以写成(x0+k*b', y0-k*a'),其中a' = a/gcd(a,b),b' = b/gcd(a, b),k取任意整数。
2、设a, b, c,为任意整数,g = gcd(a, b),方程ax+by = g的一组解是(x0, y0),则当c是g的倍数时 ax + by = c的一组解是(x0c/g, y0c/g);当c不是g的倍数时不整数解。
为什么可以这样留给大家思考。
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
typedef long long LL;
LL ax, by;
LL n, m;
LL L;
void ex_gcd(LL a, LL b, LL &d, LL &x, LL &y)
{
if(!b)
{
d = a; x = 1; y = 0;
}
else
{
ex_gcd(b, a%b, d, y, x);
y -= x*(a/b);
}
}
void solve()
{
LL d, x, y;
ex_gcd(n-m, L, d, x, y);
LL b1 = L / d;
if((ax-by) % d || m == n) { printf("Impossible\n"); return ;} //无整数解或者跳跃的距离相同。
x *= (ax-by) / d;
LL ans = (x % b1 + b1) % b1;
printf("%lld\n", ans);
}
int main()
{
while(~scanf("%lld%lld%lld%lld%lld", &ax, &by, &m, &n, &L))
{
solve();
}
return 0;
}