zoukankan      html  css  js  c++  java
  • 浅谈扩展欧几里得算法

    众所周知,扩展欧几里得算法(下文统称Exgcd)能求解二元一次方程的整数解,乘法逆元、线性模方程等。本文我将简单的介绍该算法。

    形如ax+by=gcd(a,b) 的方程,我们可以用Exgcd求出其最小整数解。我们考虑如何求解。

    当b=0时,方程右边的值为a,那么显然可得x=1,y=0。

    现在假设当前方程为ax1+by1=gcd(a,b),我们已经求得方程bx2+a%by2=gcd(a,b)的解为x2,y2,我们考虑通过x2,y2推出x1,y1的值、

    解法如下:

    因此,我们在gcd算法的代码上稍加改动,即可完成Exgcd的代码实现。

    Exgcd算法的时间复杂度与gcd相等,最坏情况下近似于O(logn)

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 int exgcd(int a, int b, int &x, int &y) {
     5     if (b == 0) {
     6         x = 1; y = 0;
     7         return a;
     8     }
     9     int gcd = exgcd(b, a % b, x, y);
    10     int x2 = x, y2 = y;
    11     x = y2;
    12     y = x2 - (a / b) * y2;
    13     return gcd;
    14 }
    15 int main() {
    16     int a, b, x, y;
    17     scanf("%d%d", &a, &b);
    18     exgcd(a, b, x, y);
    19     printf("%d %d
    ", x, y);    
    20     return 0;
    21 }
    Exgcd

    那么,我们来看看Exgcd的实际应用

    1.求解线性模方程

    参考例题【NOIP2012】同余方程

    引理:同余方程ax≡b(mod p)有解,当且仅当gcd(a,p)|b,在本题中,b=1,即gcd(a,p)=1;

    变形,得到方程ax-py=gcd(a,p),这是Exgcd的一般形式,我们套用算法即可。

    注意,本题要求出方程的最小正整数解,而Exgcd求出的是最小整数解,所以我们将答案加上p在mod p即可。

    代码略

    2.求解乘法逆元

    参考例题【洛谷3811】乘法逆元

    乘法逆元的定义:当ax≡1 (mod p)且gcd(a,p)=1时,我们称a关于模p的逆元为x

    这道题与上个例题非常相似,我们可以用同样的方法求解。

    注意,在洛谷上本题数据范围较大,使用Exgcd总的时间复杂度为O(nlogn),不能通过本题。

    求多个数的乘法逆元存在一种线性递推的方法可以在O(n)的时间内解决,由于本博客主要讲解Exgcd,所以不再赘述。

  • 相关阅读:
    Linux学习(五)
    Linux学习(四)
    Linux学习(三)
    Linux学习(二)
    Linux学习(一)
    JAVA学习笔记(九)
    JAVA学习笔记(八)
    连接报错'mysql_native_password'
    TabControl改变TabPage时自动字体变大
    问题:winform窗体与设计时不一致
  • 原文地址:https://www.cnblogs.com/shl-blog/p/11086627.html
Copyright © 2011-2022 走看看