POJ 2282 数位DP
链接:
http://poj.org/problem?id=2282
题意:
给你一个区间a,b,问a到b之间每个数字出现了多少次
题解:
看过算法设计与分析的人都很熟悉这道题,毕竟是课后练习的第一道,感觉用数位dp比模拟更好理解啊
dp[pos][sta]表示到从最低位到第pos位,第pos位为sta(0<=sta<=9)时的 num的个数。
代码:
31 int a[20]; 32 int dp[20][10]; 33 int num; 34 35 int dfs(int pos, int sta, bool lead, bool limit) { 36 if (pos == -1) return sta; 37 if (!lead && !limit && dp[pos][sta] != -1) return dp[pos][sta]; 38 int up = limit ? a[pos] : 9; 39 int res = 0; 40 rep(i, 0, up + 1) { 41 if (lead && i == 0) res += dfs(pos - 1, sta, true, limit && i == a[pos]); 42 else res += dfs(pos - 1, sta + (i == num), false, limit && i == a[pos]); 43 } 44 if (!lead && !limit) dp[pos][sta] = res; 45 return res; 46 } 47 48 int solve(int x) { 49 int pos = 0; 50 while (x) { 51 a[pos++] = x % 10; 52 x /= 10; 53 } 54 return dfs(pos - 1, 0, true, true); 55 } 56 57 int main() { 58 ios::sync_with_stdio(false), cin.tie(0); 59 int a, b; 60 memset(dp, -1, sizeof(dp)); 61 while (cin >> a >> b, a) { 62 if (a > b) swap(a, b); 63 num = 0; 64 cout << solve(b) - solve(a - 1); 65 for (num = 1; num <= 9; num++) 66 cout << ' ' << solve(b) - solve(a - 1); 67 cout << endl; 68 } 69 return 0; 70 }