最大公約數問題

2021-06-28 06:34:35 字數 1609 閱讀 3042

最大公約數是個很基本的問題。歐幾里德在他的著作裡面給出了很高效的解法,輾轉相除法。

假設f(x,y)表示x,y的最大公約數,取k=x/y,b=x%y,那麼x=ky+b,這個能說明什麼問題呢?

如果乙個數能整除x和y,那麼這個數也必定能整除y和b,並且x和y的最大公約數和y和b的最大公約數是相同的。

於是就有公式f(x,y)=f(y,x%y),於是就把原問題的最大公約數轉化為兩個更小數的最大公約數,直到乙個數為0,另乙個數則為最大公約數。

在這裡遺留乙個問題,就是沒有看輾轉相除法的證明,後面看初等數論時會補上。

舉個例子:f(36,28)=f(28,8)=f(8,4)=f(4,0)=4

解法1**:

考慮到上面解法1用到了模運算,對於大整數而言,取模運算開銷很大,那麼我們再來分析下是否不用模運算來改進演算法?

分析上面的輾轉相除法,如果乙個數能夠同時整除x,y,那麼這個數一定能夠同時整除x-y和y,也就是說f(x,y)=f(x-y,y)

改進之後的優點是:把大整數的取模運算轉化為大整數的減法,節省了開銷,但是也帶來乙個很大的缺點,那就是迭代的次數比解法1

多很多,特別是遇到(100000000,1)這種情況。

解法2**:

是否就此結束了呢?解法1的缺點是取模運算複雜,解法2的缺點是減法運算次數多,那是否能夠綜合解法1和解法2得到最佳的演算法?

我們設y=k*y1,x=k*x1,那麼f(x,y)=k*f(x1,y1).如果x=p*x1,如果p為素數,那麼y%p!=0,那麼f(x,y)=f(p*x1,y)=f(x1,y).

我們知道2也是素數,我們下面選素數作為2的最大原因是乙個2是乙個神奇的數字,特別對於二進位制的大整數來說,乘以2和除以2就可以

變成移位運算,免除大整數的除法運算,在這裡不得不說我看到了數學之美,程式設計之美。

下面就用2來具體分析:

如果x和y都是偶數:f(x,y)=f(x/2,y/2)=2*f(x>>1,y>>1)

如果x是偶數,y是奇數:f(x,y)=f(x/2,y)=f(x>>1,y)

如果x是奇數,y是偶數:f(x,y)=f(x,y/2)=f(x,y>>1)

如果x和y都是奇數 ,沒有什麼辦法,就只有做減法了:f(x,y)=f(x-y,y)。

那麼之後x-y又是偶數,下一步又會有除以2的操作。

f(36,28)=f(100100,11100)=2*f(10010,1110)=4*f(1001,111)

=4*f(10,111)=4*f(111,10)=4*f(111,1)=4*f(110,1)

=4*f(11,1)=4*f(10,1)=4*f(1,1)=4*f(0,1)=4*f(1,0)=4

解法3**如下:

演算法3巧妙地運用了移位運算和減法運算,避免了大整數的除法運算和取模運算,很大地提高了演算法的效率。

我們也再次見證了位運算的強大!

最大公約數

1.執行最大公約數的常用演算法,並新增異常處理模組 如輸入非法等 在基礎程式的基礎上,可以考慮手動輸入所有數字或者利用隨機數產生數字,分別加入異常處理模組。注 隨機數的產生方法 srand 的作用是提供乙個種子。然後呼叫rand 其格式為int rand void 它會根據提供給srand 的種子值...

最大公約數

最大公因數 greatest common divisor 也稱最大公約數 最大公因子,指兩個或多個整數共有約數中最大的乙個。a,b的最大公約數記為 a,b 同樣的,a,b,c的最大公約數記為 a,b,c 多個整數的最大公約數也有同樣的記號。求最大公約數有多種方法,常見的有質因數分解法 短除法 輾轉...

最大公約數

求兩數的最大公約數 簡單嗎?簡單!用多種方法求,可以嗎?emmmmm.應該可以吧?相信絕大多數人都知道求最大公約數的如下 所示的這種方法 include includeint commondivisor int x,int y min return min int main 先判斷兩個數的大小,將較...