UVA 埃及分数问题

题目大意:给定一个分数a/b,他可以被表示成多个单位分数(1/a)之和的形式,如2/3=1/2+1/3,而且可能不止一种,如5/12=1/3+1/12=1/4+1/6.要求你写出给定分数a/b的单位分数之和的形式,若不止一种,则选择项数最少的,若项数相等,则选择最小元素最大的,若最小元素相等则选择第二小元素最大的,。。。。



#define _CRT_SECURE_NO_WARNINGS  
#include<iostream>  
#include<algorithm>  
#include<string>  
#include<sstream>  
#include<set>  
#include<vector>  
#include<stack>  
#include<map>  
#include<queue>  
#include<cstdlib>  
#include<cstdio>  
#include<cstring>  
#include<cmath> 
typedef long long LL;
LL a,b;
int ans[5000];
int maxd=1;
int best[5000];
LL get_first(LL a,LL b){//找到并返回使(1/c)小于(a/b)的最小c 
	LL c;
	if (b%a==0) c=b/a;
	else c=(b/a)+1;
	return c;
}



bool isbetter(){
	
   for (int i = maxd; i >= 1; i--)//由于分母是由小到大存储的,因此逆序枚举  
   if (ans[i] != best[i])  
        return best[i] == -1 || ans[i]<best[i];  
    return false; 

}

LL gcd(LL a, LL b)  
{  
    return b == 0 ? a : gcd(b, a%b);  
}



bool dfs(int d,LL c,LL a,LL b){//还剩a/b,接下来取的分数 
	bool ok=false;
	if (d==maxd-1){//只能再加一个了 
		if(b%a==0) {
			ans[maxd]=b/a;
			if (isbetter()){
				memcpy(best+1,ans+1,maxd*sizeof(int));
				return true;
			}
		
		}
		 return false;
	}
	LL from=c>get_first(a,b)?c:get_first(a,b);//取两者之大着
	for (int i=from;;i++){
		//乐观的估计i及之后的可不可以取
		if((maxd-d)*b<a*i) {
			break;
		}
		ans[d+1]=i;
		LL bb=b*i;
		LL aa=a*i-b;
		int g=gcd(aa,bb);
		if(dfs(d+1,c+1,aa/g,bb/g)) ok=true;
		
	} 
	
	return ok;
}



int main(){
	int num=1;
while(scanf("%ld %ld",&a,&b)){
	maxd=1;
	memset(best,-1,sizeof(int)*5000);
	while (!dfs(0,get_first(a,b),a,b))	{
			maxd++;
		}
	 printf ("Case %d:%d/%d=",num,a,b);
	 for (int i=1;i<=maxd;i++){
	 	printf ("1/%d",best[i]);
	 	if (i<maxd) printf ("+");
	 }
	 printf("\n");
	 num++;
}
	

	 return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值