题目:青蛙的约会
思路:首先本题可以用常规的解法求得一个扩展的欧几里德的算法公式。为了保证能够相遇,A 和 B 的总路程的差值一定是纬度长的整数倍。
令 跳跃 t 次后相遇, 有
(x + m * t) - (y + n * t) = l * k
转化公式有:
x-y = (n-m) * t + l * k
令 d = x-y; a = n-m; b = l; 有
d = a * t + b * k = gcd(a, b)
在解这道题的时候,我并没有对扩展的欧几里德算法有所了解,所以很多的问题都没有得到很好的解释,也看不懂,通过这道题让我对欧几里德的算法应用,有了更进一步的了解。学习算法的重要性在于使用算法解决实际的问题。
#include <iostream>
using namespace std;
int gcd(int a, int b) {
if (a < b)
swap(a, b);
int r = a % b;
if (r == 0)
return b;
return gcd(b, r);
}
void extern_gcd(unsigned int a, unsigned int b, unsigned int c, int & x, int & y) {
int d = b;
int r = a % b;
if (r == 0) {
x = 0;
y = 0;
if (d == c)
y = 1;
return ;
}
int tmpx = 0;
int tmpy = 0;
extern_gcd(b, r, c, tmpx, tmpy);
x = tmpy;
y = tmpx - (a / b) * tmpy;
return ;
}
int main() {
int x = 0;
int y = 4;
int n = 4;
int m = 2;
int l = 8;
int t = 0;
int k = 0;
int times = 0;
cout << "Input: " << x << "," << y << "," << n << "," << m << "," << l << endl;
// (y - x) = (n - m) * t + l * k
x = x % l;
y = y % l;
int yx = y - x;
if (yx < 0) yx += l;
int nm = n - m;
if (nm < 0) {
nm = -nm;
yx = l - yx;
}
if (nm > 0) {
int gcd_yx = yx / gcd(yx, gcd(nm, l));
int knm = gcd_yx * nm;
int kl = gcd_yx * l;
extern_gcd(knm, kl, yx, t, k);
times = gcd_yx * t;
}
cout << "Output: ";
if (times > 0)
cout << times << endl;
else
cout << "Impossible" << endl;
return 0;
}
我对这道题有太多的感慨,网上的文章只是告诉我使用扩展的欧几里德算法,但是并没有告诉我如何使用这个算法。
使用扩展的欧几里德算法有两个基本的限制
- 所有的输入输出必须全是整数,、
- 构造一个原组(a, b),a和b的最大公约数是d
依赖上述的条件我们能算得一个等式:
d = ax + by;
你可以从我的代码上看到这个特点,我辛辛苦苦的就是为了凑了上述的限制,然后才能使用扩展的欧几里德算法。
从这道题我看到了对于算法的变通和数学上使用的转换算法是如此的相似!!!