有三个算法:一是著名很简单的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;
}
其中注意ans = 0的时候要输出长度L!~