1025 - 搜索优化之迭代加深 - 埃及分数

埃及分数

描述

任何一个分数都能才成若干个单位分数(形如1/a的, a是自然数)的和。
对于一个分数a/b,表示方法有很多种,但是哪种最好呢?
首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越好,如果还是相同,那么第二小的分数越大越好,依次类推下去。
例如对于19/45,下列方法都是合法的

19/45=1/3 + 1/12 + 1/180

19/45=1/3 + 1/15 + 1/45

19/45=1/3 + 1/18 + 1/30,

19/45=1/4 + 1/6 + 1/180

19/45=1/5 + 1/6 + 1/18.

但是最好的是最后一种,因为1/18比1/180,1/45,1/30,1/180都大。
现在给出a,b(0<a<b<1000),求最好的表达方式。

输入

a b

输出

若干个数,自小到大排列,依次是单位分数的分母

样例输入

19 45

样例输出

5 6 18


分析

所谓迭代加深,其实就是限制深度的dfs
每次确定一个dfs的深度
而对于这道题:
在这里插入图片描述

全局long long真好用


代码
#include<bits/stdc++.h>
#define re register
#define N 100000
#define int long long
using namespace std;
int a,b,ans[N],tmp[N];
int get(int x,int y){return y/x+1;}
int gcd(int x,int y){
	int z=x%y;
	while(z){x=y;y=z;z=x%y;}
	return y;
}
bool better(int len){
	for(int i=len;i>=0;--i)
		if(ans[i]!=tmp[i])
			return ans[i]==-1||tmp[i]<ans[i];
	return false;
}
bool dfs(int limit,int d,int from,int x,int y){
	if(d==limit){
		if(y%x) return false;
		tmp[d]=y/x;
		if(better(d)) memcpy(ans,tmp,sizeof(tmp));
		return true;
	}
	int flag=0;
	from=max(from,get(x,y));
	for(int i=from;;i++){
		if(1ll*y*(limit-d+1)<=1ll*x*i) break;
		int xx,yy;
		tmp[d]=i;
		xx=1ll*x*i-y;
		yy=y*i;
		int gd=gcd(xx,yy);
		if((dfs(limit,d+1,i+1,xx/gd,yy/gd))) flag=1;
	}
	return flag;
}
signed main(){
	cin>>a;cin>>b;
	int sta=get(a,b),i,j;
	for(i=1;;i++){
		memset(ans,-1,sizeof(ans));
		if(dfs(i,0,sta,a,b))		break;
	}
	for(j=0;j<=i;++j) cout<<ans[j]<<' ';
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值