hdu 3886 Final Kichiku “Lanlanshu(数位DP进阶)

意义:
给一个模式。求区间中匹配这个模式的数的个数。
思路:
这道题其实。。挺考代码能力的。。
递归的状态定义成
dp (int pos, int pre, int idx, int nolead, int limit, int ctl)
其中(idx)是下一个被匹配的模式,当前正在匹配的模式是(idx-1)。
ctl用来控制是否将上界本身计入,这样就不用写字符串加1了。

char buf[105], A[105], B[105];
LL f[105][10][105], d[105], L;
const LL Mod = 100000000;

int check(int idx, int first, int second) {
    char ch = buf[idx];
    if (ch == '/') return first < second;
    if (ch == '-') return first == second;
    if (ch == '\\') return first > second;
}

LL dp(int pos, int pre, int nolead, int idx, int limit, int ctl) {
    if (pos < 0) {
        if (ctl && limit) return 0;
        return idx == L;
    }
    // 特判 limit 的情况,防止重复计数
    if (limit || f[pos][pre][idx] == -1) {
        LL ret = 0, last;
        last = limit ? d[pos] : 9;
        rep(i, 0, last) {
            if (!nolead) ret += dp (pos-1, i, nolead || i, idx, limit && (i == last), ctl), ret%=Mod;
            else if (idx < L && check(idx, pre, i))
                ret += dp (pos-1, i, nolead || i, idx+1, limit && (i == last), ctl), ret%=Mod;
            else if (idx > 0 && check(idx-1, pre, i))
                ret += dp (pos-1, i, nolead || i, idx, limit && (i == last), ctl), ret%Mod;
        }
        if (limit) return ret;
        f[pos][pre][idx] = ret;
    }
    return f[pos][pre][idx];
}

LL solve(char * ptr, int ctl) {
    //cout << "debug:\n";
    int idx = 0, h = 0, len = strlen(ptr);
    while (ptr[h] == '0' && h < len-1) ++h;
    urep(i, len-1, h) d[idx++] = ptr[i] - '0';
    //cout << "d: ";urep(i, idx-1, 0) cout << d[i];cout << endl;
    memset(f, -1, sizeof(f));
    return dp (idx-1, 0, 0, 0, 1, ctl);
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in", "r", stdin);
#endif
    //SPEED_UP
    int kase = 0;
    LL aa, bb;
    while (scanf("%s", buf) != EOF) {
        scanf("%s%s", A, B);
        L = strlen(buf);
        aa = solve(A, 1);
        bb = solve(B, 0);
        printf("%08I64d\n", ((bb-aa)%Mod+Mod)%Mod);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值