hdu3652_数位dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3652

题意就是求区间内能被13整除并且包含”13“的数字的个数

定义dp[len][mod][mark];

其中len表示当前正在处理的位数或可以理解为还有len位需要处理,mod表示当前的总的余数(即从最高位到len位时所计算得到的余数)

mark起标记作用

mark==0表示从最高位到i位还没有出现”13“;

mak==1表示从最高位到i位没有出现”13“,但第i位为1

mark==2表示从最高位到i位包含”13“

flag 标记是否达到上限

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cstdio>
 6 #include <vector>
 7 #include <ctime>
 8 #include <queue>
 9 #include <list>
10 #include <set>
11 #include <map>
12 using namespace std;
13 #define INF 0x3f3f3f3f
14 typedef long long LL;
15 
16 int bit[15], dp[15][15][5];
17 int Dfs(int len, int mod, int mark, int flag)
18 {
19     int sum = 0;
20     if(len == 0)
21         return mod == 0 && mark == 2;
22     if(flag && dp[len][mod][mark] >= 0)
23         return dp[len][mod][mark];
24     int te = flag ? 9 : bit[len];
25     for(int i = 0; i <= te; i++)
26     {
27         int Mod = (mod * 10 + i) % 13;
28         int Mark = mark;
29         if(mark != 2 && i != 1)
30             Mark = 0;
31         if(mark != 2 && i == 1)
32             Mark = 1;
33         if(mark == 1 && i == 3)
34             Mark = 2;
35         sum += Dfs(len - 1, Mod, Mark, flag || i < te);
36     }
37     if(flag)
38         dp[len][mod][mark] = sum;
39     return sum;
40 }
41 int main()
42 {
43     int n;
44     while(~scanf("%d", &n))
45     {
46         memset(bit, 0, sizeof(bit));
47         int len = 0;
48         while(n)
49         {
50             bit[++len] = n % 10;
51             n /= 10;
52         }
53         memset(dp, -1, sizeof dp);
54         cout<< Dfs(len, 0, 0, 0)<<endl;
55     }
56     return 0;
57 }
View Code

 

posted @ 2016-08-15 16:48  海无泪  阅读(112)  评论(0编辑  收藏  举报