問題描述:
求兩個整數的最大公約數,如果這兩個數很大,演算法該如何改
分析與解法一:
歐幾里得演算法——輾轉相除,這是很經典的求最大公約數問題,其原理描述如下:兩個數x,y,x>y,則x=ky+b,如果乙個數m能整除x與y,即x/m沒有餘數,y/m沒有餘數,則x/m=ky/m+b/m,所以,b/m是沒有餘數的,這說明x,y若能被m整除,則y,b也能被m整除,這就是輾轉的原理。
分析與解法二:
歐幾里得演算法的原理是除,要知道,除是很消耗cpu的時鐘的,所以有必要進行進一步的改進。從歐幾里得演算法可以得到啟發,若x,y都能被m整除,可以很容易得到結論,x-y,y都能被m整除,那麼不斷輾轉相減,就可以得到最後的最大公約數。
這個演算法,免去了大整數除法的繁瑣,但是也有不足之處。例如遇到(100000000000,1)這種情況就不好了。
分析與解法三:
第三種解法利用上面兩種解法,通俗的講,每一次的迭代,該用減法還是除法,根據上一步的迭代結果而定。
具體的講,演算法改進的目標是:1)盡量減小迭代次數;2)盡量少用除模運算。
有趣的是用除模運算可以大幅度減小迭代的次數,但是這與盡量少用除模運算想矛盾,因此,演算法的目的在於在除模與減法運算之間找到乙個平衡點。
注意以下兩點性質:
1) 若(x,y)能被m整除,那麼f(x,y)=m(x/m,y/m);
2) 若x=p*x1,且p為素數,不能整除y,那麼f(x,y)=f(px1,y)=f(x1,y)。
關鍵在於第二點,乙個數x如果可以分解為乙個素數p和另乙個數相乘x1,且這個y%p不等於0,那麼x1與y的最大公約數等於x與y,這是乙個很好的用除法減小迭代次數的方法。那麼如何知道乙個數是否能被乙個素數相除?
應該想到2是乙個素數,能不能被2整除,也就是進行奇偶判定。因此,演算法的思路如下:
1)x,y為偶數,f(x,y)=2f(x>>1,y>>1)
2)x為偶,y為奇,f(x,y)=f(x>>1,y)
3)x為奇,y為偶,f(x,y)=f(x,y>>1)
4)x,y為奇,f(x,y)=f(x-y,y)
重新開始戰鬥03 程式設計之美 買書問題
問題描述 由於 哈利波特 系列相當暢銷,店長決定通過 活動來回饋讀者。上櫃的 哈利波特 瓶裝本系列中,一共有5卷。假設每一捲單獨銷售均需8歐元。如果讀者一次購買不同的兩卷,就可以扣除5 的費用,三卷更多。具體的折扣如下 本數 折扣 2 5 3 10 4 20 5 25 每本書只能享受一種折扣。例如買...
重新開始戰鬥05 程式設計之美 光影切割
問題描述 假設有乙個矩形區域,有若干條直線切割該區域,並且沒有一條直線與y軸平行,且不存在三條 以及3條以上 切割線相交於一點的情況。請問該矩形平面被分割成多少塊。分析 假設一塊矩形區域已經被切割成很多塊,那麼此時再增加一條切割線,新的切割線與其他切割線相交,且有m個交點。那麼新的切割線被分割成m ...
重新開始戰鬥04 程式設計之美 尋找ID問題
問題描述 乙個很大的列表 有10億多個數 這個列表中全是都是id號,正常狀態下每個id都會再列表中出現兩次 都是亂序 1.當有乙個id號丟失時,如何找到這個id號 2.當有兩個id號丟失時,如何找到這兩個id號。解法一 最直觀 申請乙個陣列,這個陣列和id列表一樣大,然後遍歷id列表,每遍歷乙個id...