[codevs 1288] 埃及分数 迭代加深搜索

我怎么今天专挑毒瘤题做啊… 一天两道题怕是破纪录了…

这个题还是算一个比较好的模板

当我们枚举一个深度 设当前分数和为 s u m 最终结果为 l a s t

则把 ( l a s t s u m ) / ( 1 / i ) 作为估价函数, 如果这个值已经大于当前选定分数个数加上最优补数大于枚举深度的话就可以 r e t u r n 了, 然后这个题是一个很垃圾很垃圾的题, 希望你们不要碰它(手动微笑

如果你硬要写的话注意以下两点
1.这题精度会爆翻, 千万不要用 d o u b l e ,一定要手写分数啊啊啊啊啊

2.这是一道垃圾卡常题,如果你对自己的常数不自信的话就一定要注意再注意啊.

欢迎挑战垃圾题

90ptsCodes

#include<bits/stdc++.h>
#define For(i, a, b) for(register int i = a; i <= b; ++ i)
#define PII pair<ll, ll>
#define less lunch
#define mp make_pair

using namespace std;
typedef long long ll;

const int maxn = 100 + 10;
int maxd, now[maxn], a, b, flag, ans[maxn];
PII finnal;

bool equal(PII x, PII y) {
    return x.first == y.first && x.second == y.second;
}

bool less(PII x, PII y) {
    bool fux = x.first < 0, fuy = y.first < 0;
    if(fux ^ fuy) return fux;   
    if(fux && fuy) return less(mp(-y.first, y.second), mp(-x.first, x.second));
    return x.first * y.second < y.first * x.second;
}   

PII add(PII x, PII y) {
    ll sonx = x.first, sony = y.first, momx = x.second, momy = y.second;
    ll lcm = momx / __gcd(momx, momy) * momy, sons = (sonx * (lcm / momx)) + (sony * (lcm / momy));
    ll gcd = __gcd(sons, lcm);
    return mp(sons / gcd, lcm / gcd);
}

void judge() {
    for(int i = maxd; i >= 1; -- i) {
        if(now[i] >= ans[i]) return;
        For(j, 1, maxd) ans[j] = now[j];
        return;
    }
}

inline bool dfs(int x, PII sum) {
    if(equal(sum, finnal)) return judge(), true;
    if(x == maxd) return false;
    PII Fuck = add(finnal, mp(-sum.first, sum.second)); 
    int from = max(now[x], int(1.0 * Fuck.second / Fuck.first) - 1);
    int To = Fuck.second * (maxd - x) / Fuck.first;
    for(register int i = from + 1; i <= To; ++ i) {
        PII to = add(sum, mp(1, i));
        if(less(finnal, to)) continue;
        PII ovo = add(sum, mp(maxd - x, i));
        if(less(ovo, finnal)) break;
        now[x + 1] = i;
        if(dfs(x + 1, to)) flag = true;
    }
    return flag;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("1288.in", "r", stdin);
    freopen("1288.out", "w", stdout);
#endif
    memset(ans, 0x3f, sizeof(ans));
    scanf("%d%d", &a, &b);
    ll gcd = __gcd(a, b);
    finnal = mp(a / gcd, b / gcd);
    for(maxd = 0; ; ++ maxd) 
        if(dfs(0, mp(0, 1))) {
            For(i, 1, maxd) 
                printf("%d ", ans[i]);
            break;
        }
    cerr << 1.0 * clock() / CLOCKS_PER_SEC << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lunch__/article/details/81394867