您的位置:首页 > 其它

POJ 1061 青蛙的约会

2014-01-10 23:59 363 查看
假设两只青蛙跳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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息