題干
古埃及人只用分子為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;
}
總結
課本上把這道題的算法歸類到貪心
應該就是在求最大的埃及分數那一步體現出來的。你要求最少的埃及分數,那就是要求每次分解出來的埃及分數盡可能地大,這樣就減少了分解出來的埃及分數的個數。