扩展欧几里得算法及应用

落爺英雄遲暮 提交于 2020-02-03 01:38:16

欧几里得算法

即利用辗转相除法求最大公因数

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

裴蜀定理(贝祖定理)

若a,b是整数,那么一定存在整数x,y,使ax+by=gcd(a,b)成立

重要推论:a和b互质的充要条件是存在整数x,y,有ax+by=1

扩展欧几里得算法

扩展欧几里得算法又称exgcd,就是利用欧几里得算法,求出贝祖定理ax+by=gcd(a,b)的整数解

证明:

∵gcd(a,b)=gcd(b,a%b),gcd(b,a%b)=bx+(a%b)y

∴a1x1+b1y1=gcd(a1,b1)=gcd(b1,a1%b1)=b1x2+(a1%b1)y2

令a2=b1,b2=a1%b1

∴a1x2+b2y2=gcd(a2,b2)=gcd(b2,a2%b2))=b2x3+(a2%b2)y3

同理…

最后可化简为gcd(an,0)=anxn+0*yn=an

得到最后一组解为xn=1,yn=0

∵a%b=a-a/b*b,其中a/b是计算机除法,不是数学意义的除法

在第一次我们化简的等式中有a1x1+b1y1=b1x2+(a1%b1)y2

∴a1x1+b1y1=b1x2+(a1-a1/b1*b1)y2=a1y2+b1(x2-a1/b1*y2)

∴x1=y2,y1=x2-a1/b1*y2

然后由最后一组解回溯,即可求得x1,y1

下面的代码中是简洁版本:我们都是由下一层得到上一层的,当我们由最后一层返回倒数第二层的时候,我们把y传给上一层的x,这样由上面公式来看是正确结果,而上一层的y怎么求呢,上一层的y等于下一层的x减去a/b乘以下一层的y。而下一层的y我们已经赋值给了当前层的x,下一层的x我们已经赋值给了当前层的y,因此仔细思考,y-=(a/b)*x;就可以得到当前层的y,再一层层向上传递即可

代码之所以返回a,b的最大公因数是因为我们可能用到,这样就不需要再求一遍gcd了

int exgcd(int a,int b,int &x,int &y){
    if(!b){
        x=1;y=0;
        return a;
    }
    int gcd=exgcd(b,a%b,y,x);
    y-=(a/b)*x;
    return gcd;     //返回的是a,b的最大公因数
}

应用

1.求解二元一次不定方程

已知ax+by=c,设r=gcd(a,b),则

  • 若c%r!=0,该方程组无整数解

  • 若c%r==0,我们可以先求出ax+by=r对应的一组整数解,然后再乘以c并除以r即可得到ax+by=c的整数解(求的是其中的一组特殊解)

2.求逆元

若a*x在模p意义下的结果为1,那么称x为a在模p意义下的逆元,x又写作a-1记作ax ≡ 1 (mod p)

那么我们可以转化为求解ax+py=1

由于最后的求得的x可能是负数,因此我们再进行处理:(x%p+p)%p

int exgcd(int a,int b,int &x,int &y){
    if(!b){
        x=1;y=0;
        return a;
    }
    int gcd=exgcd(b,a%b,y,x);
    y-=(a/b)*x;
    return gcd;     //返回的是a,b的最大公因数
}

ll inv(ll a,ll p){
	ll x,y;
	exgcd(a,p,x,y);
    return (x%p+p)%p;
}

3.求解线性同余方程

暂时不会,以后再补

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!