HDU 5898:odd-even number(数位DP)

http://acm.hdu.edu.cn/showproblem.php?pid=5898

题意:给出一个区间[l, r],问其中数位中连续的奇数长度为偶数并且连续的偶数长度为奇数的个数。(1<=L<=R<= 9*10^18)

思路:在比赛的时候只大概记得是怎么写的,但是就是不会写,虽然写过好几道可还是写不出来。回去后重新写又错了几次,主要前导零的情况没有考虑清楚。存的时候存长度和之前一位是偶数还是奇数和是否有前导零。然后根据条件判断才写了出来。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <string>
 5 #include <cmath>
 6 #include <iostream>
 7 #include <stack>
 8 #include <map>
 9 #include <queue>
10 using namespace std;
11 #define N 100010
12 #define INF 0x3f3f3f3f
13 
14 long long dp[25][25][2][2];
15 int bit[25];
16 //pos记录第几位,len记录目前的段的长度,pre记录之前一个位是奇偶,zero判断前导零
17 long long dfs(int pos, int pre, int len, int zero, bool f)
18 {
19     if(pos <= 0) return (pre & 1) != (len & 1);
20     if(f && dp[pos][len][pre][zero] != -1) return dp[pos][len][pre][zero];
21     int d = f ? 9 : bit[pos];
22     long long ans = 0;
23     for(int i = 0; i <= d; i++) {
24         if(zero == 0) { //如果前面都是0,记得特殊考虑这种情况
25             if(i == 0) ans += dfs(pos - 1, 0, 0, 0, f || i < d);
26             else ans += dfs(pos - 1, i & 1, 1, 1, f || i < d);
27         } else {
28             if(i & 1) {
29                 if(pre & 1) ans += dfs(pos - 1, i & 1, len + 1, 1, f || i < d);
30                 else {
31                     if(len & 1) ans += dfs(pos - 1, i & 1, 1, 1, f || i < d);
32                 }
33             } else {
34                 if(pre & 1) {
35                     if(!(len & 1)) ans += dfs(pos - 1, i & 1, 1, 1, f || i < d);
36                 } else {
37                     ans += dfs(pos - 1, i & 1, len + 1, 1, f || i < d);
38                 }
39             }
40         }
41     }
42     if(f) dp[pos][len][pre][zero] = ans;
43     return ans;
44 }
45 
46 long long solve(long long x)
47 {
48     int len = 0;
49     while(x) {
50         bit[++len] = x % 10;
51         x /= 10;
52     }
53     return dfs(len, 0, 0, 0, 0);
54 }
55 
56 int main()
57 {
58     int t;
59     scanf("%d", &t);
60     for(int cas = 1; cas <= t; cas++) {
61         memset(dp, -1, sizeof(dp));
62         long long l, r;
63         scanf("%I64d%I64d", &l, &r);
64         printf("Case #%d: %I64d
", cas, solve(r) - solve(l - 1));
65     }
66     return 0;
67 }
原文地址:https://www.cnblogs.com/fightfordream/p/5885788.html