埃及分数
- 题意:需要表示的分数a/b(0<a<b<1000),求出最好的表达方式中各个单位分数的分母。最好表达式:加数最少且分母越小。
- 分析:想到使用dfs,但时间开销大,使用IDDFS。然后考虑处理分数的问题。
- 分数处理
- 将分子用a表示,将分母用b表示。a/b-1/i=ai/bi+b/bi=(ai-b)/bi.当a==1时,最后一个分母为b,再进行判断。
- 优化分母下限:设当前深度到极限深度值为k,当前分母为i,k(1/i)>a/b即k(y/x)>i
- 优化分母上限:(1).当前分母大于上一个分母;(2).1/i<a/b即i<b/a; 二者最大值为上限。
code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int N=1005;
int na,nb,m,dp,res[N],ans[N];
bool flag;
int gcd(int a,int b)
{
if (b==0) return a;
return gcd(b,a%b);
}
void iddfs(int t,int a,int b)
{
if (t-1==dp) return;
if (a==1)
{
if (b>res[t-1])
{
res[t]=b;
if (!flag||ans[t]>res[t]) memcpy(ans,res,sizeof(res));
flag=true;
}
return;
}
int resa,resb,m;
for (int i=(dp-t+1)*b/a; i>=max(res[t-1]+1,b/a+1); i--)
{
res[t]=i;
resa=a*i-b; resb=b*i;
m=gcd(resa,resb);
resa/=m; resb/=m;
iddfs(t+1,resa,resb);
res[t]=0;
}
}
int main()
{
scanf("%d%d",&na,&nb);
m=gcd(na,nb);
na/=m; nb/=m;
while (!flag)
{
dp++;
memset(res,0,sizeof(res));
memset(ans,0,sizeof(ans));
iddfs(1,na,nb);
}
for (int i=1; i<=dp; i++) printf("%d ",ans[i]); printf("\n");
return 0;
}
注:在rqnoj上提交,oj数据有问题