扩展欧几里得算法(exgcd) 学习笔记

定义

首先引入一个叫做贝祖定理的东西

对于 a,bN,x,yZ,使ax+by=(a,b)

已知 a,b ,求 ax+by=(a,b) 一组可行解的算法即为扩展欧几里得算法。

算法流程

首先我们知道用来求最大公因数的欧几里得算法。

int gcd(int a,int b)
{
    if (!b) return a;
    else return gcd(b,a/b)
}

扩展欧几里得其实是在欧几里得算法的基础上运行的,时间复杂度也在 log 级别。
假设现在 ax+by=(a,b) ,那么 (b,a%b)=(a,b) ,所以 bx+(a%b)y=(a,b)
又因为 a%b=a(a/b)b ,所以
(a,b)=bx+(a(a/b)b)y=bx+ay(a/b)by=ay+b(x(a/b)y)
由此可以知道下一组满足条件的解为 x=y,y=x(a/b)y
当b=0时,即a为最大公因数。这时只需要保证a的系数即x=1即可,y取任意值都不影响,不妨设y=0。
这就是整个扩展欧几里得算法的过程。

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

其实扩展欧几里得还有更简单的写法(from fye)

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

实际问题

实际上,在用exgcd解决问题的时候还有一些问题。

一般型等式

比如要求 ax+by=c 的值,首先可以将等式两遍同时除以 (a,b) ,如果不能整除则无解,因为c无论如何不为ab的倍数。
那么现在等式变成了 ax+by=c(a,b)=1 ,为了满足扩欧的条件使 ax+by=(a,b)=1 ,可以将等式两遍同时除以c,得到 axc+byc=1 。这样就可以直接利用exgcd求出 xc yc 的值,然后再乘回去就可以了。
还有就是,用exgcd求出来的想x,y满足这样的性质 {|x|+|y|}min ,证明戳这里
求出来可行解了之后再将x不断-b/(a,b),y不断+a/(a,b),解仍然成立。

逆元

ax1(modp),(a,p)=1 ,则x为a的逆元。
将等式化简即可得到 axpy=1 ,即为exgcd的经典模型。

你可能感兴趣的:(数学相关,学习笔记)