题目:
- 链接:牛客网华为机试题
- 分子为1的分数称为埃及分数。现输入一个真分数(分子比分母小的分数,叫做真分数),请将该分数分解为埃及分数。
- 如:8/11 = 1/2+1/5+1/55+1/110。
- 输入描述:
输入一个真分数,String型
- 输出描述:
输出分解后的string
- 示例:
样例输入:
8/11
样例输出:
1/2+1/5+1/55+1/110
解题思路1:
【贪心算法】
设a、b为互质正整数,a < b 分数a/b 可用以下的步骤分解成若干个单位分数之和:
- 步骤一: 用b 除以a,得商数q 及余数r。(r=b - a*q)
- 步骤二:把a/b 记作:a/b=1/(q+1)+(a-r)/b(q+1)
- 步骤三:重复步骤2,直到分解完毕
按照上面的方法:
3/7=1/3+2/21=1/3+1/11+1/231
13/23=1/2+3/46=1/2+1/16+1/368
以上其实是数学家斐波那契提出的一种求解埃及分数的贪心算法,准确的算法表述应该是这样的:
设某个真分数的分子为a,分母为b;
把b除以a的商部分加1后的值作为埃及分数的某一个分母c;
将a乘以c再减去b,作为新的a;
将b乘以c,得到新的b;
如果a大于1且能整除b,则最后一个分母为b/a;算法结束;
或者,如果a等于1,则,最后一个分母为b;算法结束;
否则重复上面的步骤。
备注:事实上,后面判断a是否大于1和a是否等于1的两个判断可以合在一起,
即:判断b%a是否等于0,最后一个分母为b/a,显然是正确的。
C/C++代码:
#include <iostream>
#include <cstring>
using namespace std;
int main(){
string s;
while(cin>>s){
string s1, s2;
int a = 0, b = 0, c = 0, r = 0;
int n = s.length();
int x = s.find('/');
s1 = s.substr(0,x);
s2 = s.substr(x+1);
//cout << "x:" << x << " s1: " << s1 << " s2: " << s2 << endl;
for(int i = 0; i < s1.length(); i++){
a = a * 10 + s1[i]-'0';
}
for(int i = 0; i < s2.length(); i++){
b = b * 10 + s2[i]-'0';
}
//cout << a << " " << b << endl;
r = b%a;
if(r == 0){
cout << "1/" << b/a << endl;
continue;
}
while( r != 0){
c = b/a + 1;
cout << "1/" << c << "+";
a = a * c - b;
b = b * c;
r = b%a;
}
cout << "1/"<< b/a << endl;
}
return 0;
}
但是,由于这题的答案不唯一,在牛客网运行时的通过率仅为60%,所以,牛客网上的提供的标准解并不标准。
按照上面的算法得到:
8/11 = 1/2+1/5+1/37+1/4070
由此可见答案并不唯一。
为了通过这题,下面介绍第二个解题方法:
解题思路2:
【真分数分解为埃及分数】
* 若真分数的分子a能整除分母b,则真分数经过化简就可以得到埃及分数,
* 若真分数的分子不能整除分母,则可以从原来的分数中分解出一个分母为b/a+1的埃及分数。
* 用这种方法将剩余部分反复分解,最后可得到结果。
C/C++的代码如下:
#include <iostream>
#include <cstring>
using namespace std;
int main(){
string s;
while(cin >> s){
string s1, s2;
int a = 0, b = 0, c = 0, r = 0;
int n = s.length();
int x = s.find('/');
s1 = s.substr(0,x);
s2 = s.substr(x+1);
for(int i = 0; i < s1.length(); i++){
a = a * 10 + s1[i]-'0';
}
for(int i = 0; i < s2.length(); i++){
b = b * 10 + s2[i]-'0';
}
while(a != 1){
if(b % (a-1) == 0){
cout << "1/" << b/(a-1) << "+";
a = 1;
}
else{
c = b/a + 1;
cout << "1/" << c << "+" ;
a = a*c - b;
b = c * b;
if(b%a == 0){
b = b/a;
a = 1;
}
}
}
cout << "1/" << b << endl;
}
return 0;
}
这个代码就可以通过……
此外:
我还看到一个用Java解题的代码不错(qaq不是我写的),附上链接:大佬的java解题代码及思路