【题目描述】
两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。
我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。
【输入格式】
输入只包括一行5个整数x,y,m,n,L
其中0<x≠y < =2000000000,0 < m、n < =2000000000,0 < L < =2100000000。
【输出格式】
输出碰面所需要的天数,如果永远不可能碰面则输出一行"Impossible"。
【算法分析:】
设最少需要的次数为k,容易得出:
求一个非负整数k,使得:
可以看出,问题变成了求不定方程的x的非负最小值
求出一组x、y,使得ax+by=gcd(a,b):
ax + by = gcd(a, b) = gcd(b, a % b) = bx' + (a % b)y' = bx' + (a - [a / b] * b)y' = bx' + ay' - [a / b] * by' = ay' + b(x' - [a / b]y') ∴x = y', y = x' - [a / b] * y' 终止条件: b = 0时:a * 1 + b * 0 = a 即x = 1, y = 0 递归求解
求出一组ax+by=c的解:
用扩展欧几里得先求出ax' + by' = gcd(a, b)的一组解, x', y'及gcd(a, b)的值 若c mod gcd(a, b) ≠ 0 方程无解(整数范围内) 令: c = gcd(a, b) * k ∴k = c / gcd(a, b) ∴ax + by = c = k * gcd(a, b) ∴ax + by = akx' + bky' 根据恒等定理: ax = akx', by = bky' ∵a != 0 且 b != 0 ∴x = kx', y = ky' ∵k = c / gcd(a, b) ∴x = x' * c / gcd(a, b) y = y' * c / gcd(a, b)
使得x非负且最小:
用扩展欧几里得先求出ax' + by' = gcd(a, b)的一组解, x', y'及gcd(a, b)的值 lcm(a, b) = a * b / gcd(a, b) ax + lcm(a, b) + by - lcm(a, b) = c ax + a * b / gcd(a, b) + by - a * b / gcd(a, b) = c a(x + b / gcd(a, b)) + b(y - a / gcd(a, b)) = c ∴x + 或 - 任意倍数的b / gcd(a, b)均有对应的y的整数解 设 t = b / gcd(a, b) x = ((x' * c / gcd(a, b)) % t + t) % t 为方程的最小非负解.
扩欧代码及详解见我的github:
DEVILK1
【代码:】
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 5 int x, y, m, n, l; 6 7 int read() { 8 int x = 0, f = 1; char ch = getchar(); 9 while(ch < '0' || ch > '9') { 10 if(ch == '-') f = -1; 11 ch = getchar(); 12 } 13 while(ch >= '0' && ch <= '9') 14 x = (x << 1) + (x << 3) + (ch ^ 48), 15 ch = getchar(); 16 return x * f; 17 } 18 19 int ex_gcd(int a, int b, int &x, int &y) { 20 if(b == 0) { 21 x = 1, y = 0; 22 return a; 23 } 24 int g = ex_gcd(b, a % b, y, x); 25 y -= a / b * x; 26 return g; 27 } 28 29 int main() { 30 x = read(), y = read(); 31 m = read(), n = read(); 32 l = read(); 33 int a = n - m, c = x - y; 34 if(a < 0) a = -a, c = -c; 35 int x0, y0; 36 int g = ex_gcd(a, l, x0, y0); 37 if(c % g != 0) { 38 puts("Impossible"); 39 return 0; 40 } 41 int t = l / g; 42 x0 = ((1LL * x0 * c / g) % t + t) % t; 43 cout << x0 << endl; 44 }