原創文章,轉載請註明: 轉載自 SunliyMonkey技術博客
本文鏈接地址: 狀態轉移思想解讀:輾轉相除(歐幾里德)算法及擴展
URL: http://blog.csdn.net/sunliymonkey/article/details/48102067
1 算法實現
1.1 歐幾里德算法(輾轉相除法)
歐幾里德算法,也被稱爲輾轉相除法,其被用於求解兩個數之間的最大公約數,常用
它的算法實現十分容易,如下:
int gcd(int a,int b)
{
if(b==0)
return a;
else
return gcd(b,a%b);
}
1.2 擴展歐幾里德算法
擴展歐幾里德算法是用來求解這樣一個式子:
求解:
這裏的x,y不是唯一解,當得知一組可行解之後,其它的可行解都可以表示出來:
在這裏不闡述,x,y的值有何用處,如果你是acmer,應該發現有不少題,需要利用這個性質。
擴展歐幾里德算法的實現也很簡單,在原有歐幾里德算法的基礎上,少許額外的代碼,即能實現:
int exGcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x = 1;
y = 0;
return a;
// 此時a = gcd(A,B)
// a * 1 + b * 0 = gcd(A,B)
// 由於b=0,y可以任意取值
}
int d = exGcd(b, a%b, y, x); // 注意這裏x,y的位置對調
y -= a/b * x;
return d; // 返回最大公約數
}
2 狀態轉移思想
看了上面的實現,相信你的第一感覺是十分簡潔,確實也如此,對於一個不懂這兩種算法的人,如果提醒你從“動態規劃”,“狀態轉移”等角度思考這兩個問題,相信會有不少人能夠AC它們。
先來看看兩個明顯的結論:
如果A=B,gcd(A,B)=A或B 如果A=0,gcd(A,B)=B,同理,如果B=0,gcd(A,B)=A
看到這裏,相信你會有一種直覺:是否能夠將求解
分治: 大問題分解成小問題,小問題更容易被解決,最終,合併小問題的結果,解決大問題
動態規劃: 一個狀態能夠從多個狀態轉移而來,其最優值將從這多個狀態的最優值中選取
3 狀態轉移方程
3.1 歐幾里德
結論:
證明:
設
顯然
可以使用反證法證明:
因此
當你發現存在這樣的狀態轉移,歐幾里得算法,其實已經解決了。然後再分析下,不難發現更快速的狀態轉移方程:
而這就是上面代碼實現中,使用的狀態轉移方程。
3.2 擴展歐幾里德
有了上面狀態轉移的基礎,我們可以將問題進行如下轉換:
狀態轉移:
其中:
只需代入上面的關係,即可推導出狀態轉移的公式:
推導結果:
擴展歐幾里德算法,就這樣被你解決了!