#樸素的歐幾里得算法大家應該知道
gcd(a,b)表示a,b的最大公約數
樸素的歐幾里得算法其實就是所謂的輾轉相除法
- 輾轉相除法
gcd(a,b)=gcd(b,a mod b)
證明如下:
設r=a mod b =a−⌊ba⌋∗b,p=gcd(a,b);
則a=xp,b=yp
代入可得r=xp−⌊ypxp⌋∗yp
提公因式得r=p(x−⌊ypxp⌋∗y)
所以p∣r
即a,b的最大公約數也是r的約數
設p‘=gcd(b,r)
則b=x‘p‘,r=y‘p‘
a=r+⌊ba⌋∗b
代入得a=y‘p‘+⌊ba⌋∗x‘p‘
提公因式a=p‘(y‘+⌊ba⌋∗x‘)
所以p‘∣a
得出結論:a,b與b,a mod b的公約數相同,所以最大公約數也相同
得證;
Code:
int gcd(int a,int b)
{
if(!b) return a;
else return gcd(b,a%b);
}
擴展歐幾里得算法
擴展歐幾里得算法就是在樸素的歐幾里得算法上求一組未知數(x,y)的解,滿足貝祖定理:ax+by=gcd(a,b)
- 公式的推導
當且僅當a>b
①b=0 則x=1,y=0
②a>b>0
設ax1+by1=gcd(a,b);bx2+(a mod b)y2=gcd(b,a mod b)
由樸素歐幾里得算法得:gcd(a,b)=gcd(b,a mod b)
所以ax1+by1=bx2+(a mod b)y2
即ax1+by1=bx2+(a−⌊ba⌋∗b)y2
化簡得:ax1+by1=bx2+ay2−⌊ba⌋∗b∗y2
由貝祖等式得x1=y2y1=x2−⌊ba⌋∗b.
Code:
int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;y=0;
return a;
}
int r=exgcd(b,a%b,x,y);
int z=x;
x=y;y=z-a/b*y;
return r;
}
擴展歐幾里得應用
①解不定方程
②解線性同餘方程
③求模的逆元
1.解形如ax+by=c的不定方程
用擴展歐幾里得算法求出解ax‘+by‘=gcd(a,b)
再分別乘上gcd(a,b)c
當c mod gcd(a,b)=0時無解
2.解形如ax≡b(mod m)的線性同餘方程
即ax−my=b
ax+m(−y)=b
得出:
ax+my=b
同上解除即可。
3.求ax≡1(mod m)
由上式子可得x≡a1(mod m)
所以 x是a的逆元
同②得:ax+my=1
解出x即可.