zoukankan      html  css  js  c++  java
  • 「欧几里得与扩展欧几里得算法」学习笔记

    $$y-=x*(a/b)$$

    $$(c/g(x_0+k*b/g),c/g(y_0-k*a/g))$$

    欧几里得算法

     (gcd(a, b)) 表示 (a,b) 的最大公约数。

    欧几里得辗转相除法:

    $gcd(0,a) = a$

    $gcd(a,b) = gcd(b, a mod b), b > 0$

    算法证明

      设 $ a = bq + r $,则需证明的是 $ gcd(a,b) = gcd(b, r) $

      可以通过证明$ (a,b) $的任何公因子必定也是$ (b,r) $的公因子,且$ (b,r) $的任何公因子必定也是$ (a,b) $的公因子

      设(d)为(a, b)的任意一个约数 $ (d > 0)$,则有(d|a, d|b)。可以设(a = sd, b = td) ((s, t) 为整数)

      ∴ (r = a - bq = sd - tdq = d(s - tq))   ∴ (d|r)

      故$ (a,b) $的所有约数都是( (b,r))的约数。

      可再次证明( (b,r) )的所有约数都是( (a,b))的约数。

      故 $ gcd(a,b) = gcd(b, r) $

    扩展欧几里得算法 EXGCD

    Exgcd用来求解方程:$ ax + by = gcd(a,b) $ (关于解的存在性证明可参见 贝祖定理 )

    很明显该方程的解不止一个。先考虑解出一组特解

    求解过程

    特殊的,当$b = 0$时,$gcd(a,b) = a$,故解得$x = 1, y = 0$

    一般的,设:$$ egin{cases} ax_1 + by_1 = gcd(a,b) \ bx_2 + (a\%b)y_2 = gcd(b,a\%b) end{cases} $$

    由欧几里得算法可得$gcd(a,b) = gcd(b, a\%b)$,因此:$$ ax_1 + by_1 = bx_2 + (a\%b)y_2 $$$$ = bx_2 + (a - left lfloor a / b ight floor*b)y_2 $$$$ = bx_2 + ay_2 - left lfloor a / b ight floor*by_2 $$$$ = ay_2 + b(x_2 - left lfloor a / b ight floor y_2) $$

    因此$$ax_1 + by_1 = ay_2 + b(x_2 - left lfloor a / b ight floor y_2)$$

    由恒等式的性质可得一组特解:$$ egin{cases} x_1 = y_2 \ y_1 = x_2 - left lfloor a / b ight floor * y_2 end{cases} $$

    因此倒推即可

    void exgcd(int a, int b, int &g, int &x, int &y){
        if(!b){
            g = a; x = 1, y = 0;
            return;
        }
        exgcd(b,a%b,g,y,x);
        y -= x*(a/b);
    }

    通解求法

    设$ k_1 = left lfloor a / gcd(a,b) ight floor , k_2 = left lfloor b / gcd(a,b)  ight floor$ 。$k_1, k_2$一定互质

    同时除以$gcd(a,b)$,得$ax / gcd(a,b) + by / gcd(a,b) = 1$,即$ k_1x + k_2y = 1 $

    要求得通解,并使等式仍然成立,(x, y)不可能同时变大或变小,不然等号不能成立。故(x, y)的大小变化相反。

    设(x)增大(d_1),(y)减小(d_2), 可得(a(x + d_1) + b(y - d_2) = gcd(a, b))

    通解即为( (x + k * d_1, y - k * d_2) ) (k为常数,且为整数)

    与前面的做法相同,两边同时除以(gcd(a,b)),可得$$a(x + d_1) / gcd(a,b) + b(y - d_2)  / gcd(a,b) = 1$$

    即$$k_1(x + d_1) + k_2(y - d_2) = 1$$

    由于$k_1x + k_2y = 1$, 两边同时减去1, 得$$k_1d_1 =  k_2d_2$$

    由于(k_1, k_2)互质,故(d_1, d_2)一定可以满足$$k_1 = d_2, k_2 = d_1$$

    因此代入可得$$a(x + k_2) + b(y - k_1) = gcd(a, b)$$

    因此通解为$$ (x + k * k_2, y - k * k_1) $$

    故解得通解为$$ (x + k * left lfloor b / gcd(a,b)  ight floor, y - k * left lfloor a / gcd(a,b)  ight floor) $$

    求解线性不定方程

    求解$ax + by = c$

    当$gcd(a,b) | c$时方程一定有解,否则无解

    在方程 $ax_0 + by_0 = gcd(a,b) $ 两边同时乘以 $c / gcd(a,b)$ 可得 $ ax_0 * c / gcd(a,b) + by_0 * c / gcd(a,b) = c $

    在(a, b)的值并没有改变的情况下,原方程的解就是:$$ egin{cases} x = x_0 * c / gcd(a,b) \ y = y_0 * c / gcd(a,b) end{cases} $$

    关于最小正整数解

    由于$x$的通解是$x + k * b / gcd(a,b)$,因此最小正整数解为$x mod (b / gcd(a,b))$。前提是保证$b / gcd(a,b) > 0$。而会出现$b / gcd(a,b) < 0$的情况只有$a,b$同负或$b$为负数,因此特判$b$的正负即可

    注意当$x<0$时模一遍仍然为负数,所以需要模两遍:$$x' = (x mod (b / gcd(a,b)) + (b / gcd(a,b)) mod  (b / gcd(a,b)$$

    求解线性同余方程

    形如(ax≡b (mod m))
    由原方程(ax≡b (mod m))很容易推得( ax - b ) 是(m)的倍数。不妨设(ax - b)是(m)的(y)倍。则有方程$ ax - b = my $

    移项即可得$ ax - my = b $ 求不定方程即可

  • 相关阅读:
    java1234初学maven
    解决maven创建web项目卡死在generator插件(转)
    maven下载速度慢的解决方法(转)
    git分支
    git基础
    oracle分析函数与over()(转)
    Oracle开窗函数 over()(转)
    Oracle计算时间函数(对时间的加减numtodsinterval、numtoyminterval) (转)
    selenium使用中遇到的问题
    selenium运行火狐报错FirefoxDriver : Unable to connect to host 127.0.0.1 on port 7055
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9312928.html
Copyright © 2011-2022 走看看