扩展欧几里得算法及其应用

    扩展欧几里得算法的目的是为了计算gcd(a,b)=ax+by的一个整数根。

    过程:由欧几里得算法,gcd(a,b)=gcd(b,a mod b),可先解出gcd(b,a mod b)=bx'+(a mod b)y'再由x'、y'推出x与y。

          那么当b为0时,得出此时方程x=1,y=0。这是边界。

          当b不为0时,gcd(b,a mod b)=bx'+(a-[a/b]*b)y'=ay'+b(x'-[a/b]y')——[a/b]为a/b的下取整

          则gcd(a,b)=ay'+b(x'-[a/b]y'),则原方程有一根为x=y',y=x'-[a/b]y',只要递归求根即可

    综上若gcd(a,b)=ax+by有根x与y,则当b=0时有根x=1且y=0;否则先解出gcd(b,a mod b)=bx'+(a mod b)y',再可得出其一根x=y',y=x'-[a/b]y'。

    直接上代码。

#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
int n,m,x,y,n1,m1;
void aa(int t,int s)
 {
    if (s==0)
      {
          x=1;y=0;
          return;
      }
    aa(s,t%s);
    n1=y;m1=x-t/s*y;
    x=n1;y=m1;
    return;
 }
int main()
 {
    scanf("%d%d",&n,&m);//n、m即a、b
    aa(n,m);
    printf("%d %d\n",x,y);
    return 0;
 }

      代码略丑,轻喷。

      一个应用:解同余方程整数根

      要求同余方程ax≡b(mod n)  (n>0)的一个整数根。

      方程转换一下,(ax) mod n=b mod n,将b mod n用b'表示,方程便就是b'=ax+ny (y为整数)。不难得知方程当且仅当b'|gcd(a,n)时有解。

      则可以用ax'+ny'=gcd(a,n)的根x'、y'各乘以b'/gcd(a,n)便是x、y的值。当然这个可能比较大,还要各对n取一个模便比较合适了。

      在此不再贴代码。

      另一个运用:乘法逆元

      话说为什么叫做乘法逆元,BBG给我们直接上了群论(orzei),但貌似不需要管那么多:

      这算是针对于求(a/b) mod k的值的东西,然而当a过大,高精度又没必要,于是可以用求b关于k的乘法逆元b',使得(b*b') mod k=1,

      问题就等价于(a*b') mod k

      证明:根据b*b'≡1 (mod k)可得b*b'=k*x+1。

            b'=(k*x+1)/b。

            把b'代入(a*b') mod k=(a*(k*x+1)/b) mod k=[(a*k*x/b) mod k+a/b] mod k=(a/b) mod k。

      而 (b*b') mod k=1可以化成kx+1=b*b',其中x与b'为未知数,可以用扩展欧几里得算法求解。

      而通过欧几里得算法的性质我们知道,必须要gcd(b,k)=1方程才有解。同理,乘法逆元只在gcd(b,k)=1时存在。

原文地址:https://www.cnblogs.com/HJWJBSR/p/4119401.html