您的位置:首页 > 其它

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

2015-03-17 01:47 197 查看
意义:

给一个模式。求区间中匹配这个模式的数的个数。

思路:

这道题其实。。挺考代码能力的。。

递归的状态定义成

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: