uva 12558 Egyptian Fractions (HARD version)

https://vjudge.net/problem/UVA-12558

埃及分数问题

限制k个数不能使用

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
bool forbid[1001];
int maxd;
LL v[101],ans[101];
LL gcd(LL a,LL b) { return !b ? a : gcd(b,a%b); }
LL get_first(LL a,LL b) { return ceil(1.0*b/a); }
bool better(int d)
{
    for(int i=d;i>=0;i--)
     if(v[i]!=ans[i]) return !ans[i] || v[i]<ans[i];
    return false;
}
bool dfs(int d,LL from,LL a,LL b)
{
    if(d==maxd)
    {
        if(b%a) return false;
        if(b/a<=1000 && forbid[b/a]) return false;
        v[d]=b/a;
        if(better(d)) memcpy(ans,v,sizeof(*ans)*(d+1));
        return true;
    }
    from=max(from,get_first(a,b));
    bool ok=false;
    for(LL i=from;;i++)
    {
        if((maxd-d+1)*b<=a*i) break;
        if(i<=1000 && forbid[i]) continue;
        v[d]=i;
        LL a2=a*i-b,b2=b*i,g=gcd(a2,b2);
        if(dfs(d+1,i+1,a2/g,b2/g)) ok=true;
    }
    return ok;
}
int main()
{
    int T,a,b,k,x;
    scanf("%d",&T);
    for(int t=1;t<=T;t++)
    {
        memset(forbid,false,sizeof(forbid));
        scanf("%d%d%d",&a,&b,&k);
        while(k--) scanf("%d",&x),forbid[x]=true;
        for(maxd=1;;maxd++)
        {
            memset(ans,0,sizeof(ans));
            if(dfs(0,0,a,b))
            {
                 printf("Case %d: %d/%d=",t,a,b);
                 for(int i=0;i<maxd;i++) printf("1/%lld+",ans[i]);
                 printf("1/%lld
",ans[maxd]);
                 break;
            }
        }
    }
}
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7281930.html