codevs 1288 埃及分数

题目大意:给出一个分数,要求求出最少的x分之1的形式,如果个数相同,要求最小的数字最大。

考虑搜索,因为总个数不确定,使用IDDFS,每次确定一个长度,对于每一个位置从可以成立的最小值开始枚举。

对于最终情况:如果这次的a为1,并且b比前面的一次大,那么就是最终情况,这时如果这个长度没出现过,那么当前序列

作为答案,如果出现过,那么选择最大的最后一位作为答案。

对于搜索,每一次的新值的最小值一定要比当前的b/a大,这样1/i就比a/b大,同时也要比上一个选择i要大,因为我们选择的

答案是递增的。对于最大值,极限情况就是后续都选择i时,整体要比a/b大,所以i<(now-dep+1)*b/a。

如果最大值大于int要缩成int的极限值-1(玄学优化。。。),如果这个长度已经有过答案了,那么极限值要比目前答案的最小值

大,这样才有意义。传入下一层的就是a/b-1/i的对应分子和分母。

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll a,b,ans[15],tmp[15],now,inf=2147483647;
ll gcd(ll x,ll y)
{
	if(y==0)return x;
	return gcd(y,x%y);
}
int flag;
void dfs(ll dep,ll na,ll nb)
{
	if(dep>now)return;//这个地方也可以和下面的判断写在一起,当然了如果有最优答案早就结束了
	if(na==1&&nb>tmp[dep-1])
	{
		tmp[dep]=nb;
		if(!flag||tmp[dep]<ans[dep])
		{
			memcpy(ans,tmp,sizeof(tmp));
		}
		flag=1;return;
	}
	ll st=max(nb/na,tmp[dep-1]+1),ed=(now-dep+1)*nb/na;
	if(ed>inf)ed=inf-1;
	if(flag&&ed>=ans[now])ed=ans[now]-1;
	for(ll i=st;i<=ed;i++)
	{
		tmp[dep]=i;
		ll ty=gcd(na*i-nb,nb*i);
		dfs(dep+1,(na*i-nb)/ty,nb*i/ty);
	}
}

int main()
{
	scanf("%lld%lld",&a,&b);
	ll c=gcd(a,b);
	a/=c,b/=c;
	if(a==1)
	{
		printf("%lld\n",b);
		return 0;
	}
	tmp[0]=1;
	for(now=1;;now++)
	{
		dfs(1,a,b);
		if(flag)
		{
			for(int i=1;i<=now;i++)
			{
				printf("%lld ",ans[i]);
			}
			return 0;
		}
	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值