题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5898
一道比较简单的数位DP,需要做的就是记录当前位的前一位的奇偶以及长度。
因为不是求和,所以首先还得特判前导零的情况(如果不考虑前导零的话,偶数的长度就会出问题)。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <iostream>
using namespace std;
const int N = 100010;
const int INF = 0x3f3f3f3f;
typedef long long LL;
LL dp[25][25][2][2];
int bit[25];
LL dfs(int pos, int pre, int len, int zero, bool ismax)
{
if(pos <= 0) return (pre & 1) != (len & 1);
if(ismax && dp[pos][len][pre][zero] != -1) return dp[pos][len][pre][zero];
int Max = ismax ? 9 : bit[pos];
LL ans = 0;
for(int i = 0; i <= Max; i++)
{
if(zero == 0)
{
if(i == 0) ans += dfs(pos - 1, 0, 0, 0, ismax || i < Max);
else ans += dfs(pos - 1, i & 1, 1, 1, ismax || i < Max);
}
else
{
if(i & 1)
{
if(pre & 1) ans += dfs(pos - 1, i & 1, len + 1, 1, ismax || i < Max);
else if(len & 1) ans += dfs(pos - 1, i & 1, 1, 1, ismax || i < Max);
}
else
{
if(pre & 1)
{
if(!(len & 1)) ans += dfs(pos - 1, i & 1, 1, 1, ismax || i < Max);
}
else ans += dfs(pos - 1, i & 1, len + 1, 1, ismax || i < Max);
}
}
}
return ismax? dp[pos][len][pre][zero]=ans : ans;
}
LL solve(LL x)
{
int len = 0;
while(x)
{
bit[++len] = x % 10;
x /= 10;
}
return dfs(len, 0, 0, 0, 0);
}
int main()
{
int t;
scanf("%d", &t);
for(int cas = 1; cas <= t; cas++)
{
memset(dp, -1, sizeof(dp));
LL l, r;
scanf("%I64d%I64d", &l, &r);
printf("Case #%d: %I64d\n", cas, solve(r) - solve(l - 1));
}
return 0;
}