hdu 2669 Romantic 扩展欧几里德

利用扩展欧几里德算法可以解方程ax+by=c.

当使用扩展欧几里德算法时,当x+b时,y-a。

欧几里德算法
           定理:gcd(a,b) = gcd(b,a mod b)                      
证明:a可以表示成a = kb + r,则r = a mod b
假设d是a,b的一个公约数,则有
d|a, d|b,而r = a - kb,因此d|r
因此d是(b,a mod b)的公约数
假设d 是(b,a mod b)的公约数,则
d | b , d |r ,但是a = kb +r
因此d也是(a,b)的公约数
因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证 。
其算法:(a为任意非负整数,b为任意正整数)

/*
* hdu2669.c
*
* Created on: 2011-9-13
* Author: bjfuwangzhu
*/

#include<stdio.h>
int x, y;
int extend_gcd(int a, int b) {
if (b == 0) {
x = 1, y = 0;
return a;
}
int d = extend_gcd(b, a % b);
int tx = x;
x = y, y = tx - a / b * y;
return d;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
int a, b, d;
while (scanf("%d %d", &a, &b) != EOF) {
d = extend_gcd(a, b);
if (d != 1) {
puts("sorry");
continue;
}
while (x < 0) {
x += b, y -= a;
}
printf("%d %d\n", x, y);
}
return 0;
}

欧几里德算法
           定理:gcd(a,b) = gcd(b,a mod b)                      
证明:a可以表示成a = kb + r,则r = a mod b
假设d是a,b的一个公约数,则有
d|a, d|b,而r = a - kb,因此d|r
因此d是(b,a mod b)的公约数
假设d 是(b,a mod b)的公约数,则
d | b , d |r ,但是a = kb +r
因此d也是(a,b)的公约数
因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证 。
其算法:(a为任意非负整数,b为任意正整数)

把这个实现和Gcd的递归实现相比,发现多了下面的x,y赋值过程,这就是扩展欧几里德算法的精髓。
可以这样思考:
对于a' = b, b' = a % b 而言,我们求得 x, y使得 a'x + b'y = Gcd(a', b')
由于b' = a % b = a - a / b * b (注:这里的/是程序设计语言中的除法)
那么可以得到:
a'x + b'y = Gcd(a', b') ===>
bx + (a - a / b * b)y = Gcd(a', b') = Gcd(a, b) ===>
ay +b(x - a / b*y) = Gcd(a, b)
因此对于a和b而言,他们的相对应的p,q分别是 y和(x-a/b*y)

对于解方程主要部分说明:
1.首先给出两个定理(证明请查看相关数论书):
   A. 方程 ax = b (mod n) 有解, 当且仅当 gcd(a, n) | b;
   B. 方程 ax = b (mod n) 有d个不同的解, 其中 d = gcd(a, n);
2.证明方程有一解是: x0 = x'(b/d) mod n;
   由 a*x0 = a*x'(b/d) (mod n)
         a*x0 = d (b/d) (mod n)   (由于 ax' = d (mod n))
                 = b (mod n)
   证明方程有d个解: xi = x0 + i*(n/d) (mod n);
   由 a*xi (mod n) = a * (x0 + i*(n/d)) (mod n)
                             = (a*x0+a*i*(n/d)) (mod n)
                             = a * x0 (mod n)             (由于 d | a)
                             = b

求解模线性方程
语法:result=modular_equation(int a,int b,int n);
参数: a、b、n: ax=b (mod n) 的对应参数
返回值:方程的解

/*
* hdu2669.c
*
* Created on: 2011-9-13
* Author: bjfuwangzhu
*/

#include<stdio.h>
int x, y;
int extend_gcd(int a, int b) {
if (b == 0) {
x = 1, y = 0;
return a;
}
int d = extend_gcd(b, a % b);
int tx = x;
x = y, y = tx - a / b * y;
return d;
}
void modular_equation(int a, int b, int n) {
int e, i, d;
d = extend_gcd(a, n);
if (b % d) {
puts("No answer!");
return;
}
e = (x * (b / d) % n + n) % n;
for (i = 0; i < d; i++) {
printf("The %dth answer is: %d\n", i + 1, (e + i * (n / d)) % n);
}
printf("\n");
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
int a, b, n;
while (scanf("%d %d %d", &a, &b, &n) != EOF) {
modular_equation(a, b, n);
}
return 0;
}


这样我们就可以求出方程的所有解了,但实际问题中,我们往往被要求去求最小整数解,所以我们就可以将一个特解x,t=b/(a,b),x=(x%t+t)%t;就可以了。

posted @ 2011-10-11 20:08  qingyezhu  阅读(403)  评论(0编辑  收藏  举报