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\n", solve(num)); 49 } 50 return 0; 51 }