將真分數分解爲埃及分數

題目描述

分子爲1的分數稱爲埃及分數。現輸入一個真分數(分子比分母小的分數,叫作真分數),請將該分數分解爲埃及分數。如:8/11 = 1/2+1/5+1/55+1/110。

輸入描述

輸入一個真分數,String型

輸出描述

輸出分解後的string

輸入例子

8/11

輸出例子

1/2+1/5+1/55+1/110

算法實現

import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

/**
 * Declaration: All Rights Reserved !!!
 */
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
//        Scanner scanner = new Scanner(Main.class.getClassLoader().getResourceAsStream("data.txt"));
        while (scanner.hasNext()) {
            String real = scanner.next();
//            System.out.println(convert(real));
//            System.out.println(convert2(real));
            System.out.println(convert3(real));
        }
        scanner.close();
    }

    /**
     * 方法一
     * 真分數分解爲埃及分數
     * 解題思路
     * <p>
     * 【貪心算法】
     * 設a、b爲互質正整數,a < b 分數a/b 可用如下的步驟分解成若干個單位分數之和:
     * 步驟一: 用b 除以a,得商數q1 及餘數r1。(r1=b - a*q1)
     * 步驟二:把a/b 記做:a/b=1/(q1+1)+(a-r)/b(q1+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,顯然是正確的。
     *
     * @param real 真分數
     * @return 埃及分數
     */
    private static String convert(String real) {

        String[] parts = real.split("/");

        // 分子
        int a = Integer.parseInt(parts[0]);
        // 分母
        int b = Integer.parseInt(parts[1]);
        StringBuilder builder = new StringBuilder(64);
//        System.out.print("[1]" + a + "/" + b + ": ");

        while (b % a != 0) {
            // 求商
            int q = b / a;
            // 餘數
            int r = b % a;

            builder.append(1).append('/').append(q + 1).append('+');
            a = a - r;
            b = b * (q + 1);

        }

        builder.append(1).append('/').append(b / a);


        return builder.toString();
    }

    /**
     * 方法二
     * 真分數分解爲埃及分數
     * <p>
     * 若真分數的分子a能整除分母b,則真分數通過化簡就能夠獲得埃及分數,
     * 若真分數的分子不能整除分母,則能夠從原來的分數中分解出一個分母爲b/a+1的埃及分數。
     * 用這種方法將剩餘部分反覆分解,最後可獲得結果。
     *
     * @param real 真分數
     * @return 埃及分數
     */
    private static String convert2(String real) {

        String[] parts = real.split("/");

        // 分子
        int a = Integer.parseInt(parts[0]);
        // 分母
        int b = Integer.parseInt(parts[1]);
        StringBuilder builder = new StringBuilder(64);
//        System.out.print("[2]" + a + "/" + b + ": ");

        while (b % a != 0) {
            // 分解出一個分母爲b/a+1的埃及分數
            int c = b / a + 1;
            a = a * c - b;
            b = b * c;

            builder.append(1).append('/').append(c).append('+');
        }

        builder.append(1).append('/').append(b / a);


        return builder.toString();
    }


    /**
     * 方法三
     * 真分數分解爲埃及分數
     *
     * @param real 真分數
     * @return 埃及分數
     */
    private static String convert3(String real) {

        String[] parts = real.split("/");

        // 分子
        int a = Integer.parseInt(parts[0]);
        // 分母
        int b = Integer.parseInt(parts[1]);
        StringBuilder builder = new StringBuilder(64);

        int c;
        while (a != 1) {
            if (b % (a - 1) == 0) {
                builder.append("1/").append(b / (a - 1)).append('+');
                a = 1;
            } else {
                c = b / a + 1;
                builder.append("1/").append(c).append('+');
                a = a * c - b;
                b = c * b;
                if (b % a == 0) {
                    b = b / a;
                    a = 1;
                }
            }
        }
        builder.append("1/").append(b);
        return builder.toString();
    }
}
相關文章
相關標籤/搜索