1. 程式人生 > 其它 >埃及分數

埃及分數

題幹

古埃及人只用分子為1的分數,在表示一個真分數時,將其分解為若干個埃及分數之和。例如,7/8表示為 1/2+1/3+1/24。要求把一個真分數表示為最少的埃及分數之和的形式。更加詳細的描述請自行百度。

思路

要求表示為最少的埃及分數之和的形式,那就要求我們分解出來得到埃及分數的分母儘可能的小。
按照貪心的策略,我們可以在每一次分解時都取出最大的那個埃及分數,也就是分母最小的埃及分數。然後將所給的真分數分解為一個更小的真分數+埃及分數的形式,然後對該真分數繼續分解,直到把真分數都表示成埃及分數的形式。
那麼,現在的問題就轉成了怎麼求出每次的最大的埃及分數了。下面就行相應分析:

假設一個真分數為\(\frac{a}{b}\)

,那麼就有\(b>a\),那麼,\(b\)就可以表示成以下形式:

\[\begin{eqnarray*} &&b=a*k+c \\ &&\Rightarrow \frac{b}{a}=k+\frac{c}{a} \\ &&\Rightarrow \frac{a}{b}=\frac{1}{k+ \frac{c}{a} },\frac{c}{a}<1\\ &&\Rightarrow \frac{a}{b}=\frac{1}{k+ \frac{c}{a} }>\frac{1}{k+ 1 } \end{eqnarray*} \]

那麼,\(\frac{a}{b}\)

的最大埃及分數為\(\frac{1}{k+1}\),那麼,問題應該就可以解決了。

程式碼

/* 埃及分數 */
#include <algorithm>
#include <iostream>
using namespace std;
void eg_score(int a, int b) {
    cout << "a/b =";
    while (a > 1) {
        int k = b / a + 1;
        cout << "1/" << k << "+";  
        a = a * k - b;   //求拆解後的分子和分母
        b = b * k;
        int r = __gcd(a, b);  //這裡是求a,b的最大公約數
        if (r > 1) {          //將拆解過後的分數化為真分數
            a = a / r;
            b = b / r;
        }
    }
    cout << "1/" << b;
}

int main() {
    int a, b;
    cin >> a >> b;
    eg_score(a, b);
    return 0;
}

總結

課本上把這道題的演算法歸類到貪心應該就是在求最大的埃及分數那一步體現出來的。你要求最少的埃及分數,那就是要求每次分解出來的埃及分數儘可能地大,這樣就減少了分解出來的埃及分數的個數。