輾轉相除法


2018-03-11 17:39:22

一、輾轉相除法

在數學中,輾轉相除法,又稱歐幾里得算法英語:Euclidean algorithm),是求最大公約數的算法。

證明:

記gcd(a, b) = d

r = a - bk,r 是b對a的余數,由於a是d的倍數,b是d的倍數,k是整數,那么r必是d的倍數。

因此gcd(a, b) == gcd(b, a % b)

    private int gcd(int x, int y) {
        return y == 0 ? x : gcd(y, x % y);
    }

 

二、擴展歐幾里得 / 貝祖定理

定理:等式 ax + by = c (其中a,b,c均是整數)存在整數解的充要條件是c % gcd(a, b) == 0,也就是說c是a,b最大公約數的倍數。

證明:

記gcd(a, b) = d

輾轉相除的過程如下

a / b = s1 ... r1

b / r1 = s2 ... r2

r1 / r2 = s3 ... r3

...

rn - 1 / rn = sn + 1 ... rn + 1

rn / rn + 1 = sn + 2 ... d

現在開始反代,

 

d = rn - rn + 1 * sn +2

此時,d是可以通過rn,rn + 1組合得到。

將rn + 1消掉

d = rn - (rn - 1 - rn  * sn + 1

此時,d是可以通過rn - 1,rn 組合得到。

同理消除,最后d可以通過a,b組合得到。

 

三、Water and Jug Problem

問題描述:

有兩個容量分別為 x升 和 y升 的水壺以及無限多的水。請判斷能否通過使用這兩個水壺,從而可以得到恰好 z升 的水?

如果可以,最后請用以上水壺中的一或兩個來盛放取得的 z升 水。

你允許:

裝滿任意一個水壺
清空任意一個水壺
從一個水壺向另外一個水壺倒水,直到裝滿或者倒空
示例 1: (From the famous "Die Hard" example)

輸入: x = 3, y = 5, z = 4
輸出: True

示例 2:

輸入: x = 2, y = 6, z = 5
輸出: False

問題求解:

如果單純的去思考兩個杯子之間的倒來倒去,那么問題就會變得非常復雜。有一種簡化思路是,考慮有一個大的杯子,而x,y只是向大杯子中添加或者取出水,如果最終大杯子中數目等於給定的數,那么返回true。

其實就是尋找z = ax + by等式是否有解,也就是規約到了裴蜀定理的概念中,只需要判斷z % gcd(x, y)即可。

    public boolean canMeasureWater(int x, int y, int z) {
        if (x + y < z) return false;
        if (x == z || y == z || x + y == z) return true;
        return z % gcd(x, y) == 0;
    }
    
    private int gcd(int x, int y) {
        return y == 0 ? x : gcd(y, x % y);
    }

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM