• 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;就可以了。

  • 相关阅读:
    Windows下使用CMake编译SuiteSparse成VS工程
    【设计模式
    【设计模式
    vue过滤和复杂过滤
    el-tooltip 自定义样式
    el-table加表单验证
    使用Go env命令设置Go的环境
    面试官:GET 和 POST 两种基本请求方法有什么区别?
    解决 Vue 重复点击相同路由报错的问题
    利用promise和装饰器封装一个缓存api请求的装饰器工具
  • 原文地址:https://www.cnblogs.com/xiaoxian1369/p/2207725.html
Copyright © 2020-2023  润新知