[hdu 5898 odd-even number] 数位DP
题目链接:[hdu 5898 odd-even number]
题意描述:求区间
[L,R]
中有多少个数字
x
,满足十进制展开形式的连续个奇数的长度为偶数,连续个偶数的长度为奇数。
解题思路:裸的数位DP。 只要记录好当前位的奇偶性以及当前连续的长度,是否前导零。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned __int64 ULL;
const int BITS = 25;
const int DIGS = 2;
const int STATUS = 2;
int T, cas;
LL L, R;
LL dp[BITS][DIGS][STATUS];
int dig[BITS];
LL dfs(int pos, bool pre, bool status, bool limit, bool zero) {
if(pos < 1) return zero ? 0 : status;
if(!zero && !limit && dp[pos][pre][status] != -1) return dp[pos][pre][status];
int last = limit ? dig[pos] : 9;
bool nstat, now;
LL ret = 0;
for(int i = 0; i <= last; i++) {
now = (i & 1);
if(zero) {
nstat = !now;
} else {
if(pre ^ now) {
if(status == false) continue;
nstat = !now;
} else {
nstat = !status;
}
}
ret += dfs(pos - 1, now, nstat, limit && (i == last), zero && (i == 0));
}
if(!zero && !limit) dp[pos][pre][status] = ret;
return ret;
}
LL solve(LL x) {
int len = 0;
while(x) {
dig[++ len] = x % 10;
x /= 10;
}
return dfs(len, false, true, true, true);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif // ONLINE_JUDGE
cas = 0;
scanf("%d", &T);
memset(dp, -1, sizeof(dp));
while(T --) {
scanf("%I64d%I64d", &L, &R);
printf("Case #%d: %I64d\n", ++cas, solve(R) - solve(L - 1));
}
return 0;
}