[ZJOI2010]数字计数【数位DP】

题目链接

   很明显的数位DP,但是为什么会有0分的情况呢?可能有这样的两种情况没有考虑到:

1000000000000 1000000000000

  

100 110

  

  首先,想到的是做一个差分的办法来解决这个问题,那么就是求0~X的这样的一个前缀0、1、2、3、…… 、9在数位中出现了多少次。很明显的,就是求每个数位上对应每个数所产生的贡献了,同时,前导零不能算进去。

  那么,如果没有前导零的时候,实际上贡献就比较的好算了,以它为中间的某个值的时候,后面有多少个数就是这个数位对应数的产生的贡献了。当然还要注意的一点是,如果它是作为前导零出现的,那么可能还不能把它更新进答案里面去,以它作为上限值(阈值)的时候,也是不能把它当作记忆化更新的。

  作为阈值的时候,答案不完整。

  存在前导零的时候,计数的个数还未更新到位,对后继答案有影响。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <string>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <limits>
 8 #include <vector>
 9 #include <stack>
10 #include <queue>
11 #include <set>
12 #include <map>
13 #include <bitset>
14 #include <unordered_map>
15 #include <unordered_set>
16 #define lowbit(x) ( x&(-x) )
17 #define pi 3.141592653589793
18 #define e 2.718281828459045
19 #define INF 0x3f3f3f3f
20 #define HalF (l + r)>>1
21 #define lsn rt<<1
22 #define rsn rt<<1|1
23 #define Lson lsn, l, mid
24 #define Rson rsn, mid+1, r
25 #define QL Lson, ql, qr
26 #define QR Rson, ql, qr
27 #define myself rt, l, r
28 #define pii pair<int, int>
29 #define MP(a, b) make_pair(a, b)
30 using namespace std;
31 typedef unsigned long long ull;
32 typedef unsigned int uit;
33 typedef long long ll;
34 struct node
35 {
36     ll a[10], num; bool flag;
37     node() { memset(a, 0, sizeof(a)); num = 0; flag = false; }
38     friend node operator + (node e1, node e2)
39     { for(int i = 0; i <= 9; i ++) e1.a[i] += e2.a[i]; return e1; }
40     friend node operator - (node e1, node e2)
41     { for(int i = 0; i <= 9; i ++) e1.a[i] -= e2.a[i]; return e1; }
42 } dp[15][10];
43 int dig[15];
44 ll a, b;
45 node dfs(int pos, int x, bool top, bool zero)
46 {
47     node ans, tmp;
48     ll num = 0;
49     if(pos <= 1) { ans.a[x] ++; ans.num = 1; return ans; }
50     if(!top && dp[pos][x].flag) return dp[pos][x];
51     int u = top ? dig[pos - 1] : 9;
52     for(int i = 0; i <= u; i ++)
53     {
54         ans = ans + (tmp = dfs(pos - 1, i, top && (i == u), zero && (!i)));
55         if(!zero) num += tmp.num;
56     }
57     ans.a[x] += num;
58     ans.num = num;
59     if(!top && !zero)
60     {
61         dp[pos][x] = ans;
62         dp[pos][x].flag = true;
63     }
64     return ans;
65 }
66 int main()
67 {
68     scanf("%lld%lld", &a, &b); a --;
69     for(int i = 1; i <= 14; i ++)
70     {
71         dig[i] = a % 10;
72         a /= 10;
73     }
74     for(int i = 0; i <= 14; i ++) for(int j = 0; j <= 9; j ++) dp[i][j] = node();
75     node x = dfs(14, 0, true, true);
76     for(int i = 1; i <= 14; i ++)
77     {
78         dig[i] = b % 10;
79         b /= 10;
80     }
81     for(int i = 0; i <= 14; i ++) for(int j = 0; j <= 9; j ++) dp[i][j] = node();
82     node y = dfs(14, 0, true, true);
83     node ans = y - x;
84     for(int i = 0; i <= 9; i ++) printf("%lld%c", ans.a[i], i == 9 ? '
' : ' ');
85     return 0;
86 }
原文地址:https://www.cnblogs.com/WuliWuliiii/p/14135195.html