形如:1/a 的分数称为单位分数。
可以把1分解为若干个互不相同的单位分数之和。
例如:
= 1/2 + 1/3 + 1/9 + 1/18
= 1/2 + 1/3 + 1/10 + 1/15
= 1/3 + 1/5 + 1/7 + 1/9 + 1/11 + 1/15 + 1/35 + 1/45 + 1/231
等等,类似这样的分解无穷无尽。
我们增加一个约束条件:最大的分母必须不超过30
请你求出分解为n项时的所有不同分解法。
数据格式要求:
输入一个整数n,表示要分解为n项(n<12)
输出分解后的单位分数项,中间用一个空格分开。
每种分解法占用一行,行间的顺序按照分母从小到大排序。
例如,
输入:4
程序应该输出:
1/2 1/3 1/8 1/24
1/2 1/3 1/9 1/18
1/2 1/3 1/10 1/15
1/2 1/4 1/5 1/20
1/2 1/4 1/6 1/12
再例如,
输入:5
程序应该输出:
1/2 1/3 1/12 1/21 1/28
1/2 1/4 1/6 1/21 1/28
1/2 1/4 1/7 1/14 1/28
1/2 1/4 1/8 1/12 1/24
1/2 1/4 1/9 1/12 1/18
1/2 1/4 1/10 1/12 1/15
1/2 1/5 1/6 1/12 1/20
1/3 1/4 1/5 1/6 1/20
由于分数运算会导致精度丢失,所以必须用求出最小公倍数的方法来解决这道题目。
package com.xjj.lqtest;
import java.util.Scanner;
/*----求分子数--Dfs算法--最小公倍数-----
*
* */
public class T {
public static int N;
public static int[] a; //存分子数的数组
public int[] book = new int[30]; //标记的数组
int t = 0; //最小公倍数的中间值
//求两个数的最小公倍数,此算法也可求最大公约数,两数之乘除以最大公约数=最小公倍数
public int minmul(int m, int n){
int a = m,b = n;
while(n != 0){
int t = m % n;
m = n;
n = t;
}
return a*b/m;
}
//DFS算法
public void dfs(int nowNum, int step, int min){
int sum = 0;
//将公倍数除以每个数之和
for(int i = 0; i < step; i++){
sum += min/a[i];
}
//大于则无需再继续往下搜索,直接返回
if (sum > min) {
return;
}
//如果刚和等于公倍数,满足要求
if (step == N) {
if (sum == min) {
for(int i = 0; i < N; i++)
System.out.print("1/" + a[i] + " ");
System.out.println();
}
return;
}
for(int i = nowNum + 1; i < 30; i++){
if (book[i] == 0) { //判断是否已经遍历
a[step] = i;
book[i] = 1; //标记该数已经遍历
t = minmul(min, i); //求最小公倍数
dfs(i, step+1, t); //深度搜索
book[i] = 0; //解除该标记
}
}
return;
}
public static void main(String[] args) {
System.out.println();
Scanner scanner = new Scanner(System.in);
N = scanner.nextInt();
a = new int[N];
T t = new T();
t.dfs(1, 0, 1);
}
}