Java机试题*:将真分数分解为埃及分数(斐波那契求真分数的埃及分数)
描述
分子为1的分数称为埃及分数。现输入一个真分数(分子比分母小的分数,叫做真分数),请将该分数分解为埃及分数。如:8/11 = 1/2+1/5+1/55+1/110。
注:真分数指分子小于分母的分数,分子和分母有可能gcd不为1!
如有多个解,请输出任意一个。
请注意本题含有多组样例输入!
输入描述:
输入一个真分数,String型
输出描述:
输出分解后的string
/**
数学家斐波那契提出的一种求解埃及分数的贪心算法,准确的算法表述应该是这样的:
设某个真分数的分子为a,分母为b;
把c=(b/a+1)作为分解式中第一个埃及分数的分母;
将a-b%a作为新的a;
将b*c作为新的b;
如果a等于1,则最后一个埃及分数为1/b,算法结束;
如果a大于1但是a能整除b,则最后一个埃及分数为1/(b/a),算法结束;
否则重复上面的步骤。
**/
/** 思路1:斐波那契求埃及分数贪心算法: **/ import java.util.*; public class Main{ public static void main(String[] args){ Scanner in = new Scanner(System.in); while(in.hasNext()){ String res = ""; String[] arr = in.nextLine().split("/"); String pre = ""; int a = Integer.valueOf(arr[0]); int b = Integer.valueOf(arr[1]); while (true){ int c = b/a+1; res += "1/"; res += c; a = a - b % a; b = b * c; res += "+"; if (a == 1){ res += "1/"; res += b; break; }else if (a > 1 && b % a == 0){ res += "1/"; res += b/a; break; } } System.out.println(res); } } }
import java.util.ArrayList; import java.util.List; import java.util.Scanner; /** * * 思路2:通分比较从1/2开始依次比较分子大小,若大于埃及分数,则减去,直到真分数分子为0,这种思路10个用例有一个超时无法通过。 * */ public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); while (in.hasNextLine()) { String[] num = in.nextLine().split("/"); long member = Long.valueOf(num[0]); long denominator = Long.valueOf(num[1]); long tempMember = member; long tempDenominator = denominator; // 存储拆分的埃及分数分母 List<Long> ret = new ArrayList<Long>(); // 从1/2 开始 long initDenominator = 2; while(tempMember > 0) { // 求分母的最小公倍数,通分比较大小 long minMultiple = getMinMultiple(tempDenominator, initDenominator); // 通分后分子 long a = tempMember * (minMultiple / tempDenominator); long b = 1 * (minMultiple / initDenominator); if(a >= b) { tempMember = a - b; tempDenominator = minMultiple; // 将满足的放入埃及分数分母结果集合 ret.add(initDenominator); } initDenominator++; } StringBuffer retStr = new StringBuffer(); for (int i = 0; i < ret.size(); i++) { retStr.append("1/" + ret.get(i) + "+"); } System.out.println(retStr.substring(0,retStr.length() - 1)); } } // 求最大公约数 public static long gcd(long a,long b) { return b == 0 ? a : gcd(b, a % b); } // 最小公倍数 public static long getMinMultiple(long m , long n) { // 最小公倍数 = 这两个数的乘积 / 最大公约数 long minMultiple = n * m / gcd(m,n); return minMultiple; } }
题目来源:牛客网