hdu 2669 Romantic 扩展欧几里德

大城市里の小女人 提交于 2019-12-30 04:41:00

利用扩展欧几里德算法可以解方程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;就可以了。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!