在學習擴歐之前,我們首先要了解下面這兩個部分的知識。給定數 \(a,b\), 求 \(gcd(a,b)\)。
也就是說,對於數 \(a,b\), \(gcd(a,b)=gcd(b,a \%b)\)
對於歐幾里得演算法,也比較好用遞迴實現。
c++**如下
int gcd(int a,int b)
若\(a,b\)是整數,且\(gcd(a,b)=d\),那麼對於任意的整數 \(x,y\),\(ax+by\) 都一定是\(d\)的倍數,特別地,一定存在整數\(x,y\),使 \(ax+by=d\)成立。
下面,可以正式進入對擴充套件歐幾里得演算法的學習了
首先,由於裴蜀定理,我們知道 \(ax+by=gcd(a,b)\) 一定存在,而擴充套件歐幾里得演算法,就是為了求出題中的\(x,y\)。
而當我們的歐幾里得演算法執行到最後一步,也就是 \(b=0\) 時,此時的 \(gcd(a,b)=a\),那麼很明顯 \(ax+by=gcd(a,b)\) 的解為 \(x=1,y=0\)。
既然知道了最後一層,那我們就可以層層遞推出第一層了(一開口就知道老千層餅了)。 但是要如何實現呢?
首先我們知道:\(a\%b=a-(a/b)*b\)(注意此處的"/"捨去餘數);代入:然後,我們就可以愉快的寫**了\(b*x_1 + (a-(a/b)*b)*y_1\)
\(= b*x_1 + a*y_1 – (a/b)*b*y_1\)
\(= a*y_1+ b*(x_1 – a/b*y_1) = gcd\) 發現 \(x_0 = y_1 , y_0 = x_1 – a/b*y1\)
引用自此處
**如下
int x,y,gcd;
void exgcd(int a, int b)
exgcd(b,a%b);//遞迴
int t=y;//遞迴返回後執行
y=x-(a/b)*y;
x=t;
}
至此,對於擴歐的學習就結束了。
讓我們來看這樣一道題
洛谷p1082 同餘方程
求關於\(x\)的同餘方程 \(ax≡1(modb)\) 的最小正整數解。由於 \(a≥2\),將上面式子化簡後我們可以得到 \(ax-by=1\)對於 100%的資料,&2 ≤a, b≤ 2,000,000,0002≤a,b≤2,000,000,000&。
輸入格式
一行,包含兩個正整數 a,ba,b,用乙個空格隔開。
輸出格式
乙個正整數 x_0,即最小正整數解。輸入資料保證一定有解。
#includeusing namespace std;
int x,y;
void exgcd(int a, int b)
exgcd(b,a%b);
int t=y;
y=x-(a/b)*y;
x=t;
}int main()
這裡有個值得注意的地方,就是 \((x+b)\%b\)。
因為題中要求的是最小正整數,所以先加,保證為正數,後取餘,保證為最小。
擴充套件歐幾里得演算法
includeusing namespace std typedef struct nodenode node t node extend euclid int a,int b else extend euclid b,a b int tmp t.x t.x t.y t.y tmp a b t.y ...
擴充套件歐幾里得演算法分析詳細
如果a,b兩數是整數,那麼一定存在整數x,y 使得 ax by bcd a,b int bcd int a,int b 這個演算法很好理解,如果實在看不懂,用筆紙帶入兩個數相信你能懂 代入數字加深理解 求 50,35 50 1 35 15 15 50 1 35 35 15 2 5 5 35 15 2...
歐幾里得演算法
歐幾里得演算法中,計算 x,y 的最大公約數的方法是輾轉相除,例如 26,15 26 15 1 11 15 11 1 4 11 4 2 3 4 3 1 1 3 1 3 0 可知,26,15 1 如果 x,y r,那麼有 ax by r,可以看出,上面的步驟實際上是可以直接得出 a,b 的 26 15...