niangniang~

先上题:

青蛙的约会

(poj1061时限1000MS,内存10000K

问题描述

两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。

我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。

输入

包括多个测试数据。每个测试数据包括一行5个整数x,y,m,n,其中x≠y < 2000000000,0 < m、n < 2000000000,0 < L < 2100000000。

输出

对于每个测试数据,在单独一行里输出碰面所需要的跳跃次数,如果永远不可能碰面则输出一行“Impossible”。

输入样例

1 2 3 4 5

输出样例

4

按照题目的讲法,我们可以列出一个方程式,假设两只青蛙能碰面,则它们的坐标要满足条件:(x+km)-(y+kn)=sL

整理式子:sL+k(n-m)= (x-y)   这里问题就变成这个式子是不是有解了。把式子整理成简单的形式:ka+sb=c ,a=n-m  b=L c=x-y 已知,k s未知

这种形式的式子解的条件是什么呢?

设d=gcd(a,b)

如果d与c没有因数,则无解。

如果d与c有因数,通解 k=k'(c/d)+(b/d)t    s=s'(c/d)-(a/d)t  t是任意整数  k' s'是ka+sb=d的一个特解。

具体证明戳这里,有做过的童鞋写的很详细~(里面也写到了关于如何得最小非负整数解的详细过程)

http://www.cnblogs.com/comeon4mydream/archive/2011/07/18/2109060.html 

可是我们可以看到这些解有无数个,符合题意的是k的最小非负整数解。通过扩展的欧几里德算法(extend_gcd)我们能得出了k' s' ,由于t是任意整数,不如直接取0(这里不影响后面运算),这样通解就直接变成了特解。这样其实整个题就变成:只要是d与c有因数,结论就是k'。但是怎样保证k'是最小非负?我盗来了上述帖子的算法,令 r = b/gcd(a, b),则最后解为:(k' % r + r) % r 。具体解释还是戳上面~

因为这位童鞋写的代码很简洁,出于膜拜和学习的心态,我就贴在下面咯~~~再次感谢~~~

 

#include <iostream> 
using namespace std; 
long long extgcd(long long a, long long b, long long &x, long long &y) 
{ 
    long long d, t; 
    if (b == 0) { x = 1; y = 0; return a; } 
    d = extgcd(b, a % b, x, y); 
    t = x - a / b * y; x = y; y = t; 
    return d; 
} 
int main() 
{ 
    long long x, y, m, n, L, X, Y, d, r; 
    while (cin >> x >> y >> m >> n >> L) 
    { 
        d = extgcd(n - m, L, X, Y); r = L / d; 
        if ((x - y) % d) cout << "Impossible" << endl; 
        else cout << ((x - y) / d * X % r + r) % r << endl; 
    } 
    return 0; 
}

完毕~