HDU 3652:B-number(数位DP)

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

题意:求数位含有13和可以被13整除的数字个数。

思路:记录3种状态:

st == 0 表示 从最高位到第 i 位既不包含 “13” 末尾也不包含 “1”。

st == 1 表示 末尾包含 “1”。

st == 2 表示 从最高位到第 i 位含有 “13”。

可以被 13 整除的话用一个参数来记录从最高位到第 i 位的和对 13 取模,当 mod == 0 && st == 2 的时候代表含有 “13” 并且可以被 13 整除。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <string>
 6 #include <cmath>
 7 #include <queue>
 8 #include <vector>
 9 using namespace std;
10 #define N 505
11 #define INF 0x3f3f3f3f
12 int dp[20][20][3];
13 int  bit[20];
14 
15 int dfs(int pos, int mo, int st, int limit)
16 {
17     if(pos <= 0) return st == 2 && mo == 0;
18     if(limit && ~dp[pos][mo][st]) return dp[pos][mo][st];
19     int d = limit ? 9 : bit[pos];
20     int ans = 0;
21     for(int i = 0; i <= d; i++) {
22         int ss = st;
23         int me = (mo  * 10 + i) % 13;
24         if(st != 2 && i != 1) ss = 0;
25         if(st != 2 && i == 1) ss = 1;
26         if(st == 1 && i == 3) ss = 2;
27         ans += dfs(pos - 1, me, ss, limit || i != d); 
28     }
29     if(limit) dp[pos][mo][st] = ans;
30     return ans;
31 }
32 
33 int solve(int num)
34 {
35     int len = 0;
36     while(num) {
37         bit[++len] = num % 10;
38         num /= 10;
39     }
40     return dfs(len, 0, 0, 0);
41 }
42 
43 int main()
44 {
45     int num;
46     while(~scanf("%d", &num)) {
47         memset(dp, -1, sizeof(dp));
48         printf("%d
", solve(num));
49     }
50     return 0;
51 }
原文地址:https://www.cnblogs.com/fightfordream/p/6021561.html