5kyu Some Egyptian fractions
题目背景:
Given a rational number n
as a string (example: “2/3” in Ruby, Python, Clojure, JS, CS, Go) or as two strings (example: “2” “3” in Haskell, Java, CSharp, C++, Swift) decompose this number as a sum of rationals with numerators equal to one and without repetitions (2/3 = 1/2 + 1/6 is correct but not 2/3 = 1/3 + 1/3, 1/3 is repeated).
The algorithm must be “greedy”, so at each stage the new rational obtained in the decomposition must have a denominator as small as possible. In this manner the sum of a few fractions in the decomposition gives a rather good approximation of the rational to decompose.
2/3 = 1/3 + 1/3 doesn’t fit because of the repetition but also because the first 1/3 has a denominator bigger than the one in 1/2 in the decomposition 2/3 = 1/2 + 1/6.
题目分析:
埃及分数是很有趣的一个数字的性质,本道题本质上是数学上的问题分析,对于大于1的部分,直接分子除以分母获取大于1的那部分整数即可;对于拆解出的小于1的部分,如果分母可以整除了分子,那么说明埃及分数的迭代结束,而倘若不能够整除,需要用到贪心思想,去找到最小的分母,譬如 6 / 14, 那么它可以生成的数里面,最小的分母是 14 / 6 (c++中int 除以 int会下取整得到int型结果 ) + 1 = 3 ,于是6 / 14 = 1 / 3 + ((3 * 6) - 14) / (3 * 14) = 1 / 3 + 4 / 42 ,按照这个思路就可以写出整个程序。
AC代码:
using namespace std;
class Decomp{
public:
static string decompose(const string &nrStr, const string &drStr);
};
string Decomp::decompose(const string &nrStr, const string &drStr){
long nr = std::stol(nrStr);
long dr = std::stol(drStr);
if ( nr == 0 || dr == 0 ) return "[]";
string res = "[";
while ( nr != 0 && dr != 0 ) {
if ( nr >= dr ) {
res += std::to_string(nr / dr);
nr -= (nr / dr) * dr;
}
else {
res += "1/";
long tmp;
if ( dr % nr == 0 ) tmp = dr / nr;
else tmp = dr / nr + 1;
res += std::to_string(tmp);
nr = nr * tmp - dr;
dr = dr * tmp;
}
res += ", ";
}
res = res.substr(0, res.size() - 2) + "]";
return res;
}