bzoj 1111

Description

给定 1000的十进制数, 求 最小的 四幂拆分 方案 有多少种

Solution

先大除法 (nlog_4(n))次取余转化为 四进制数.
然后从 低位 往 高位 (dp) .
(f[i]) 表示不往上借位的最小代价.
(g[i]) 表示往上借位的最小代价(被借的位的代价先不计算).
那么最后答案为 (f[n]+(g[n]+1)) (可以往更高位再借 (1)).

转移为
(f[i] = min(f[i-1] + a[i], g[i-1] + a[i] + 1))
(g[i] = min(f[i-1] + 4 - a[i], g[i - 1] + 3 - a[i]))

边界为
先去掉最低位的所有 (0) , 然后 (f=0,g=inf).

因为要求方案, 所以在 (f,g) 维护二元组 ((cost.ways)) 即可

Code

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cassert>
#define rep(i, a, b) for (int i = (a); i <= (b); ++ i)
#define per(i, a, b) for (int i = (a); i >= (b); -- i)
#define For(i, a, b) for (int i = (a); i < (b); ++ i)
#define foreach(it, c) for (__typeof((c).begin()) it = (c).begin(); it != (c).end(); ++ it)
#define fore(e, x, y) for (int ep = e(x), y = e[ep].y; ep; y = e[ep = e[ep].nxt].y)
using namespace std;
const int N = 1e3 + 7;
const int M = 2e3 + 7;
const int INF = 1e9 + 7;
const int Mod = 1e9;
 
inline int pls(int x, int y) {return (x + y) % Mod;}
inline int mns(int x, int y) {return pls(x, Mod - y);}
inline int mul(int x, int y) {return 1LL * x * y % Mod;}
inline int Add(int &x, int y) {return x = pls(x, y);}
 
int n, m;
char s[N];
int b[N], a[M];
 
struct rec {
    int cost, ways;
 
    inline rec operator + (const rec &v) {
        if (cost == v.cost) {return (rec){cost, pls(ways, v.ways)};}
        else return cost < v.cost ? *this : v;
    }
 
    inline rec operator + (const int d) const {
        return (rec){cost + d, ways};
    }
}f[M], g[M];
 
int main() {
#ifndef ONLINE_JUDGE
    freopen("a.in", "r", stdin);
#endif
 
    scanf("%s", s+1);
    n = strlen(s+1);
 
    rep (i, 1, n) b[i] = s[i] - '0';
    reverse(b+1, b+n+1);
     
    while (n > 0) {
        int res = 0;
        per (i, n, 1) {
            int d = res * 10 + b[i];
            b[i] = d / 4;
            res = d % 4;
        }
        while (n > 0 && b[n] == 0) --n;
        a[++m] = res;
    }
 
    int bg;
    rep (i, 1, m) if (a[i] != 0) {bg = i; break;}
 
    f[bg - 1] = (rec){0, 1}; g[bg - 1] = (rec){INF, 0};
    rep (i, bg, m + 1) {
        f[i] = (f[i - 1] + a[i]) + (g[i - 1] + (a[i] + 1));
        g[i] = (f[i - 1] + (4 - a[i])) + (g[i - 1] + (3 - a[i]));
    }
 
    printf("%d
", f[m + 1].ways);
 
    return 0;
}
原文地址:https://www.cnblogs.com/acha/p/7721712.html