有三个算法:一是著名很简单的gcd算法
其关键在于证明gcd(a, b) == gcd(b, a mod b)
利用整除性来证明,即gcd(a , b) 整除 gcd(b, a mod b),而gcd(b, a mod b)整除gcd(a ,b)
设d = gcd(a , b),a mod b = a - (a / b ) * b,所以d可以整除a mod b, d可以整除b,所以d可以整除b和a mod b 的各种线性组合。而gcd(b, a mod b)是b 和a mod b 的最小线性组合。所以d可以整除gcd(b, a mod b)。同理也可以证明gcd(b, a mod b) 整除 gcd(a , b)
二是求解线性方程ax + by = gcd(a ,b);
采用的是递归的思路,因为gcd(a ,b ) = gcd (b, a mod b)
所以解出了gcd(b, a mod b) = bx_0 + (a mod b)y_0;的话
那么gcd(a, b) = bx_0 + (a - (a / b) * b) y_0;
所以gcd(a, b) = ay_0 + (x_0 - (a / b ) * y_0);
代码:
/** *DESCRIPTION:The implement of gcd(a ,b) and ax + by = gcd(a , b) *using the equation gcd(a ,b) = gcd(b, a mod b) *gcd(a, 0) = a */ int gcd(int a, int b) { if (b == 0) { return a; } else { return gcd(b, a % b); } } void extended_gcd(long long a, long long b, long long &gcd_d, long long &x, long long &y) { if (b == 0) { gcd_d = a; x = 1; y = 0; } else { extended_gcd(b, a % b, gcd_d, y, x); y -= (a / b) * x; } }
三:求解同余模方程
ax == b (mod n)
算法导论上有详细解释
有两个定理:
(一):如果方程有解的话必定有gcd(a, n) | b
(二):如果方程有解的话有n / (gcd(a, n))个解
其中最小正数解为(x0 + n) % (n / d) (d == gcd(a , n));
其中a, b是否为负数没有影响。
poj1061:
#include <iostream> #include <stdio.h> using namespace std; void extended_eculid(long long a, long long b, long long &gcd_d, long long &x, long long &y) { if (b == 0) { gcd_d = a; x = 1; y= 0; } else { extended_eculid(b, a % b, gcd_d, y, x); y -= (a / b) * x; } } int main() { long long x, y, m, n, L; long long a, b, gcd_d, x_0, y_0, ans; while (scanf("%lld%lld%lld%lld%lld", &x, &y, &m, &n, &L) != EOF) { a = m - n; b = y - x; /* if (a < 0) { a = -a; b = -b; }*/ extended_eculid(a, L, gcd_d, x_0, y_0); if ((b % gcd_d) != 0) { cout << "Impossible" << endl; } else { ans = (x_0 * b / gcd_d) % L; ans = (ans + L) % (L / gcd_d); if (ans == 0) { ans += L; } cout << ans << endl; } } return 0; }