【codevs1288】埃及分数

这个题好难做qwq

我们可以通过限制它被拆分成多少个来对搜索进行限制,进而一步步的接近,最终找到答案,还可以通过判断分子与分母之间的关系来进行剪枝。这样减少了搜索状态,防止像dfs一样搜索过深

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
long long x,y,ans[10001],lin[10001],dep;//lin是用来临时存储可能答案的,ans数组才是最终答案,dep记录当前搜索的深度 
bool flag;
long long gcd(long long a,long long b)
{
    return a%b==0?b:gcd(b,a%b);
}
inline bool pd()
{
    return !flag||lin[dep]<ans[dep];//如果这是第一次记录答案或者是当前答案的分母要比原来答案小 
}
void dfs(long long ci,long long a,long long b)
{
    if(ci>=dep)//如果搜索到最后一层 
    {
        if(b%a==0)//如果分母能被分子整除,证明这个分数可以被化简到最简分数 
        {
            lin[ci]=b/a; 
            if(pd()) 
                memcpy(ans,lin,sizeof(ans));
            flag=1;
        }
        return;
    }
    for(long long i=lin[ci-1]+1;;i++)//枚举分子分母同乘多少 
    {
        if(a*i<b)//如果b>a*i那么剩下需要分的分数值就为负数了 
            continue;
        if(a*i>=b*(dep-ci+1))//同乘的数太大 
            break;
        lin[ci]=i;//a/b=1/y1+1/y2+....+b(n-1)/b(n-1)i+an*i-b(n-1)/bn*i 
        long long a1=a*i-b,b1=b*i,c=gcd(a1,b1);
        dfs(ci+1,a1/c,b1/c);//同除以c是为了化简 
    }
}
int main()
{
    scanf("%lld%lld",&x,&y);
    for(dep=1;;dep++)
    {
        dfs(1,x,y);
        if(flag)
        {
            for(int i=1;i<=dep;i++)
                printf("%lld ",ans[i]);
            break;
        }
    }
}

 

posted @ 2017-10-14 11:03  那一抹落日的橙  阅读(134)  评论(0编辑  收藏  举报