您的位置:首页 > 其它

codevs 1288 埃及分数

2016-09-04 23:03 387 查看
时间限制: 1 s

空间限制: 128000 KB

题目描述 Description

在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数。 如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的。 对于一个分数a/b,表示方法有很多种,但是哪种最好呢? 首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越 好。 如: 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),编程计算最好的表达方式。

输入描述 Input Description

a b

输出描述 Output Description

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

样例输入 Sample Input

19 45

样例输出 Sample Output

5 6 18

【分析】

题目好理解,做起来如同日狗。

第一道迭代加深搜索。

根据题目要求:加数越少越好,所以用迭代加深。

具体解释程序中有注释哒。

【代码】

//codevs 1288 埃及分数
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define mxn 2147483647
#define fo(i,j,k) for(long long i=j;i<=k;i++)
using namespace std;
int k;
ll a,b;
bool czy;
ll ans[20],v[20];
inline ll gcd(ll x,ll y)  //以下两个函数不用多解释
{
if(x%y==0) return y;
return gcd(y,x%y);
}
inline bool yue(ll x,ll y)
{
ll c=gcd(y,x);
x=x/c,y=y/c;
if(x==1) return 1;
return 0;
}
inline void dfs(int dep,ll aa,ll bb)
{
if(dep==k)  //满足层数后进行判断
{
if(bb%aa!=0) return;
v[k]=bb/aa;
if(v[k]!=v[k-1] && v[k]<ans[k])
{
fo(i,1,k) ans[i]=v[i];
czy=1;
}
return;
}
ll low=max(v[dep-1]+1,bb/aa);  //下界满足两个条件:比上一个大且不超过当前数字。
ll high=bb*(k-dep+1)/aa;   //上界条件:如果剩下所有分数都是这个数,能凑齐当前数字
if(high>mxn) high=mxn;     //不要超过int范围,要不太浮夸
if(k && bb/aa+k-dep+1>=ans[k]) return;  //如果最后的最优数字比当前最优解大,跳出
fo(i,low,high)
{
v[dep]=i;
ll fi=aa*i-bb,se=bb*i;  //这步是计算当前数字-1/i后所得到的答案
if(fi<=0 || se<=0) continue;  //防止出现玄学RE问题
yue(fi,se);
dfs(dep+1,fi,se);
}
}
int main()
{
scanf("%lld%lld",&a,&b);
if(yue(a,b))
{
printf("%lld\n",b);
return 0;
}
for(k=2;k<=13;k++)
{
memset(ans,0x3f,sizeof ans);
v[0]=0;
dfs(1,a,b);
if(czy)
{
fo(i,1,k) printf("%lld ",ans[i]);
printf("\n");
return 0;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: