exgcd 学习笔记
定義
又名擴(kuò)展歐幾里得算法(輾轉(zhuǎn)相除法)
是用來(lái)求 \(ax+by=gcd(a,b)\) 中未知數(shù)的算法
算法證明
拿到一組 \(a,b\) ,設(shè) \(G=gcd(a,b)\)
目標(biāo):求出滿足 \(ax+by=G(1)\) 的 \(x\) 與 \(y\)
如果 已知一組 \(x2,y2\) ,滿足 \(bx2+\) \((a\) \(mod\) \(b)y2=G(2)\)
此時(shí)結(jié)合 \((1)(2)\) 得
\(ax+by=\) \(bx2+\) \((a\) \(mod\) \(b)y2(3)\)
那么當(dāng) 如果 滿足時(shí),目標(biāo)就成了求滿足 \((3)\) 的 \(x,y\),其中 \(a,b,x2,y2\) 均已知
根據(jù)取模運(yùn)算是 \(a\) \(mod\) \(b=a-b*(a/b)\)
所以方程 \((3)\) 實(shí)則是
\(ax+by=\) \(bx2+\) \((a-b*(a/b))y2\)
\(->\) \(ax+by=bx2+ay2-b*(a/b)y2\)
\(->\) \(ax+by=ay2+b(x2-(a/b)y2)\)
那么在根據(jù)方程 \(ax+by=G(1)\) 得出一組必然的解:
\(x=y2,y=x2-(a/b)y2(4)\)
可見(jiàn)只需求出 \(x2,y2\) ,就能求出正確的 \(x,y\),問(wèn)題就轉(zhuǎn)化成了求 \(x2,y2\)
將方程 \((1)\) 與 \((2)\) 對(duì)比一下:
\(ax+by=G(1)\)
\(bx2+\) \((a\) \(mod\) \(b)y2=G(2)\)
發(fā)現(xiàn)原方程的 \(a\) 變成了 \(b\),原方程的 \(b\) 變成了 \(a\) 而已
所以新的方程也可以看做 \(ax+by=G\) 的形式,然后按照上面的程序進(jìn)行下來(lái),發(fā)現(xiàn)問(wèn)題又變?yōu)榍?\(x3,y3\) 再求 \(x4,y4\) \(......\) 即一個(gè)遞歸的過(guò)程
遞歸過(guò)程中 \(a,b\) 不斷被替換為 \(b,a\) \(mod\) \(b\),這個(gè)過(guò)程和普通的歐幾里得是一樣的,所以最后會(huì)出現(xiàn) \(a(n)=G,b(n)=0\)
那么這特就是最后一層,此時(shí)就要直接返回了,需要一組 \(x(n),y(n)\) 滿足 \(a(n)x(n)+b(n)y(n)=G(5)\),然而 \(a(n)=G,b(n)=0\),所以只要 \((5)\) 的 \(x(n)\) 取 \(1\) 就必定滿足了,\(y(n)\) 就隨便取個(gè) \(0\) 就行了
最后一層結(jié)束后,就開始返回,知道最上一層,每一層都可以通過(guò)下一層的 \(x(k+1),y(k+1)\) 求出當(dāng)前層的 \(x(k),y(k)\)
整個(gè)過(guò)程就是:以輾轉(zhuǎn)相除的方式向下遞進(jìn),不斷縮小系數(shù),保證會(huì)出現(xiàn)有確定解的最后一層
例題
題目鏈接 同余方程
問(wèn)題處理
題目問(wèn)的是滿足 \(ax\) \(mod\) \(b=1\) 的最小正整數(shù)(a,b均為正整數(shù))
問(wèn)題可以轉(zhuǎn)化成求 \(ax+by=1\) 中 \(x\) 的值,其中 \(y\) 是個(gè)引入的輔助數(shù)(y一定是一個(gè)負(fù)數(shù),但是寫成 \(+\) 的形式以便 \(exgcd\) 算法)
問(wèn)題仍需轉(zhuǎn)化,\(exgcd\) 求得是 \(ax+by=gcd(a,b)\),所以求方程 \(ax+by=m\) 必須滿足的條件就是 \(m\) \(mod\) \(gcd(a,b)=0\)
簡(jiǎn)單證明一下:
由最大公因數(shù)的定義,\(a,b\) 均是 \(gcd(a,b)\) 的倍數(shù),因?yàn)?\(m=ax+by\),所以 \(m\) 一定是 \(gcd(a,b)\) 的倍數(shù),即 \(m\) \(mod\) \(gcd(a,b)=0\)
可得這道題中,必須滿足 \(1\) \(mod\) \(gcd(a,b)=0\),那么 \(gcd(a,b)\) 就必須等于 \(1\) 了,即 \(a,b\) 互質(zhì)(數(shù)據(jù)一定是滿足的)
之后通過(guò)上述的 \(exgcd\) 算法即可,但是題目要求 \(x\) 的最小值,僅僅 \(exgcd\) 無(wú)法滿足,所以需要答案處理
答案處理
求出來(lái)的 \(x,y\) 僅僅滿足 \(ax+by=1\),而 \(x\) 不一定是最小正整數(shù)解。有可能太大,也可能是負(fù)數(shù)
解決方案是:\(x\) 批量地減去或加上 \(b\),能保證 \(ax+by=1\),因?yàn)椋?/p>
\(ax+by=1\)
\(->\) \(ax+by+k*ba-k*ba=1\)
\(->\) \(a(x+kb)+(y-ka)b=1\)
1.顯然這并不會(huì)把方程中的任何整數(shù)變?yōu)榉钦麛?shù)
2.加上或減去 \(b\) 不會(huì)使 \(x\) 錯(cuò)過(guò)任何解,可以這么理解:
已經(jīng)求出一組 \(x,y\) 使得 \(ax+by=1\),也就是 \((1-ax)/b=y\),\(y\) 是整數(shù),可見(jiàn)目前 \(1-ax\) 是 \(b\) 的倍數(shù)
現(xiàn)在給 \(x\) 加上 \(kb\)(k為整數(shù)),則變?yōu)椋?/p>
\((1-a(x+kb))/b\)
\(=(1-ax)/b+ak\)
仍滿足其為 \(b\) 的倍數(shù),由此當(dāng) \(x\) 的變化量為 \(b\) 的倍數(shù)時(shí),等式仍滿足
因此到最后,如果 \(x\) 太小就不斷 \(+b\) 直到 \(>=0\),反之則一直減直到最小正整數(shù)值,就是這么寫
x=(x%b+b)%b;
總代碼如下
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=1;
register char c=getchar();
for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0;
for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
int a,b,x,y;
int exgcd(int a,int b,int &x,int &y)
{
if(b==0) {x=1;y=0;return a;}
int d=exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
read(a),read(b);
exgcd(a,b,x,y);
x=(x%b+b)%b;
cout<<x;
}
總結(jié)
以上是生活随笔為你收集整理的exgcd 学习笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: keystone和beaengine的编
- 下一篇: C++ Qt开发:Charts折线图绑定