埃及分数是指分子是1的分数,也叫单位分数。古代埃及人在进行分数运算时。只使用分子是1的分数。因此这种分数也叫做埃及分数,或者叫单分子分数。
给定一个分数,如19/45,我们可以把它表示为1/2 + 1/12+1/180,也可以表示为1/5+1/6+1/18,哪种最好呢?首先,加数少的比加数多的好,埃及分数问题即把一个真分数表示为最少的埃及分数之和的形式,表示为最少的埃及分数之和要求其末尾的埃及分数分母尽可能达到最小,即埃及分数尽可能大。其次,加数个数相同时,最小的分数越大越好。
设输入为a/b,b/a所得整数部分为c,余数部分为d,则
等式两边同除a得:
由于d小于a,所以d/a<1,放缩得:
两边倒数得:
设e等于c+1,1/e为当前最大埃及分数
以上可知一个真分数减去其最大埃及分数后a变成a*e-b,b变成b*e,得到dfs参数变化规律,下面是代码:
import java.util.Arrays;
import java.util.Scanner;
//a/b c为b/a所得整数部分 d 为其余数部分
/*b=a*c+d
*b/a=c+d/a
*b/a=c+d/a<c+1
*a/b>1/(c+1)
*设e为c+1
*a/b-1/e=a*e-b/b*e
*由此可得一个真分数减去其最大埃及分数等于(a*e-b)/b*e
/* 埃及分数问题:
* 迭代加深搜索 从小到大枚举迭代深度上限
*/
public class EgypFrac {
static final int MAX = 1000;//最大迭代深度
public static int a,b;
public static int maxd=1;
public static int mind=1;
public static int []ans=new int[1000];//保存答案的分母
public static int []den=new int[1000];//临时保存分数的分母
public static int gcd(int a,int b)//辗转相除返回最大公约数
{
return b==0 ? a :gcd(b,a%b);
}
public static int Delimit(int x,int y){ //确定分母的下界
for (int i=2;;i++){ //即:1/i <= x/y
if (y<=x*i){
return i;
}
}
}
public static boolean Adjust(int a)
{
if(ans[a]==-1) return true;
if(ans[a]<den[a]) return false;
if(ans[a]>den[a]) return true;
for(int index=1;index<a;index++)
{
if(ans[index]==-1) return true;
if(ans[index]<den[index]) return false;
if(ans[index]>den[index]) return true;
}
return false;
}
public static boolean Iddfs(int d,int min_den,int x,int y)
{
if(d==maxd) {//到达多项式数目
if(y%x!=0) return false;//不是单位分数
den[d]=y/x;
if(Adjust(d)) {
for(int index=1;index<=d;index++)
{
ans[index]=den[index];
}
}
return true;
}
min_den=Math.max(min_den,Delimit(x,y));
boolean flag=false;
for(int e=min_den;;e++)
{
if(y*(maxd-d+1)<=e*x)
break;
den[d]=e;
//一个真分数减去一个最大埃及分数之后
//原来的a 变成了,a * e - b,原来的b变成了 b * e
int x1=x*e-y;
int y1=y*e;
int g=gcd(x1,y1);//得到公约数
if(Iddfs(d+1,e+1,x1/g,y1/g)) {//deep 加深
flag=true;
}
}
return flag;
}
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
a=sc.nextInt();
b=sc.nextInt();
if(b%a==0) {
System.out.print(a+"/"+b);
}
else {
mind=Delimit(a, b);
while(maxd!=0)
{
maxd++;//多项数深度
Arrays.fill(ans, -1);
if(Iddfs(1,mind,a,b)) {
break;
}
}
int index;
for(index=1;index<maxd;index++) {
System.out.print("1/"+ans[index]+"+");
}
System.out.print("1/"+ans[index]);
}
}
}