数论——扩展欧几里德

扩展欧几里德:

  在了解扩展欧几里德之前我们应了解gcd,也就是最大公因数的算法

  且看下面这段代码

  int gcd(int a,int b){

    if(b==0) return a;

    else return gcd(b,a%b);

  }

  当然也可以写成更为简单的三目运算符写法,减少代码长度

  int gcd(int a,int b){ return b==0?a:gcd(b,a%b); } 

  此方法称为辗转相除法

  下面进行推理

  给出两数 假定 a=16,b=12;

  求两数最大公因数

  开始模拟运算过程{

    b!=0

    返回 a=12,b=4;

    b!=0

    返回 a=4,b=0

    b=0

    给出a=4

    确实为最大公因数 

  }

  那数学的证明过程呢

  设 a/b==k....r 由此可得 r=a-k*b;其中a为被除数,b为除数,k为商,r为余数

  设c=gcd(a,b)

  即c为a和b的最大公因数

  我们不妨设a=m*c,b=n*c;

  可得式子  r=a-k*b=mc-k*nc=c(m-kn);

  然后可列出 gcd(b,r);

  所以 r=c(m-kn);

  可得 c为r的因数

  由反证法可得m-kn与n互质

  可得gcd(b,r)=c;

  所以 gcd(a,b)=gcd(b,r)

  证毕

  妙不可言啊~~~妙不可言~~~

  那接下来进入正题

  扩展欧几里得

  算法本身可以用来求解不定方程

  也可以拿来求逆元

  还可以拿来求解线性同余方程

  先介绍第一个用途

 1.扩展欧几里得求解不定方程

  二元一次不定方程即 ax+by=m;

  但我们完全可以把式子变化一下(反正对式子一无所知)

  根据百度可得

  ax+by=gcd(a,b) 有解,但zkc大佬告诉我们解不唯一

  设 ax+by=gcd(a,b)*k

  得 ax+by=d, gcd(a,b)|d;

  gcd(a,b)|d 表示 d可以整除gcd(a,b);

  当x=1,y=0时

  a=gcd(a,b);

  我们可以靠递归退回x,y到本身

  即可得出答案

   网上大佬的论证

    当 b=0 时,gcd(a,b)=a,此时 x=1 , y=0

         当 b!=0 时,

         设 ax1+by1=gcd(a,b)=gcd(b,a%b)=bx2+(a%b)y2

         又因 a%b=a-a/b*b

         则 ax1+by1=bx2+(a-a/b*b)y2

    ax1+by1=bx2+ay2-a/b*by2

    ax1+by1=ay2+bx2-b*a/b*y2

    ax1+by1=ay2+b(x2-a/b*y2)

    解得 x1=y2 , y1=x2-a/b*y2

    因为当 b=0 时存在 x , y 为最后一组解

    而每一组的解可根据后一组得到

    所以第一组的解 x , y 必然存在

  代码

  void exgcd(int a,int b){

    if(b==0){

      x=1;

      y=0;

      return;

    }

    exgcd(b,a%b);

    k=x;

    x=y;

    y=k-a/b*y;

    return;

  }

  end;

·

  

原文地址:https://www.cnblogs.com/liuhailin/p/11008714.html