拓展欧几里得学习小记

来源:互联网 发布:js设置innerhtml 编辑:程序博客网 时间:2024/05/16 01:18

前言

今天的比赛第一题就是解线性同余方程,大概思路是有了,就是在求非质数模的时候卡住了。这时我才开始后悔之前没有好好学学拓展gcd,然后弱弱地打了个欧拉函数求逆元,结果还WA掉了QAQ。比赛完后赶紧恶补了一下。


算法功能

拓展欧几里得算法(Extended Euclidean Algorithm)是基于欧几里得而来解一类特殊的线性丢番图方程(Diophantine equation)的算法。

Ax+By=gcd(A,B)

运用这个丢番图方程能有效解决许多数论问题。


算法解析

预备知识

欧几里得算法(gcd),基本的解方程步骤。

算法步骤

和普通的欧几里得算法一样,拓展欧几里得算法先通过辗转相除法求得gcd(A,B)
考虑在递归回退过程中,我们已经知道了bx+(a mod b)y=gcd(A,B)我们通过下列变形来得到方程ax+by=gcd(A,B)的解:

gcd(A,B)=b×x+(a mod b)×y=b×x+(aab×b)×y=a×y+b×(xab×y)

由此可得方程ax+by=gcd(A,B)的解为
x=y,y=xaby

如普通欧几里得算法,当b=0时,a=gcd(A,B),故这时返回方程解x=1,y=0即可(显然当x,y如刚才所述时,ax+by=gcd(A,B))。然后像上述方法层层处理。
时间复杂度与普通欧几里得算法一样O(logn2)
详细可见代码实现。


代码实现

void extended_gcd(int &a,int &b){    if (!b)    {        gcd=a;        a=1;        b=0;        return;    }    int a2=b,b2=a%b;    extended_gcd(a2,b2);    b=a2-(a/b)*b2;    a=b2;}

算法用途

求解模意义下乘法逆元

显然,求a关于p的乘法逆元,即解ax1(mod p)(gcd(a,p)=1)可以通过解方程ax+py=1来完成。因为方程可以变形为

ax+pyax+pyaxax=11(mod p)1py(mod p)1(mod p)

然后x其实就是a的逆元。
这种求逆元算法比费马小定理求逆元运用范围更广,因为p不一定是质数,只用与a互质。比欧拉定理求逆元更加高效。

解不定方程

证明:对于不定方程ax+by=c,可以证明方程有整数解当且仅当gcd(a,b)|c

由裴蜀定理,方程ax+by=gcd(a,b)一定存在整数解。
由于gcd(a,b)|a,gcd(a,b)|b,故gcd(a,b)|(ax+by)
如果方程有实数解(在实数范围内成立),那么用c替换ax+by,得到gcd(a,b)|c
证毕。

求其中一组解

前提条件:该不定方程存在整数解
我们先求ax+by=gcd(a,b)
d=cgcd(a,b),那么x=dx,y=dy一定是该不定方程的一组整数解。

1 0