描述
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3555
给你一个数 N,问在从 1 ~ N 的数中有多少个数包含 “49”,其中 4 和 9 必须是连续的。
例如 1 ~ 500中,有 49, 149, 249, 349, 449, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499 一共 15 个数包含 “49”,所以答案是 15。
思路
题目范围已经到了 long long 的边界了,暴力肯定不可行。
然后这个题看起来就是数位DP的简单题 😂。只要在dfs()函数中记录下上一个数是不是 4 就可以了,然后将算好的值存在 dp 数组中,记忆化搜索,这样便可以算出有多少个数不包含 “49”,再做一下减法就是答案了。唯一要注意的也就是这个题的范围了。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| #include <iostream> #include <cstdio> #include <cstring> #define MAX 20 using namespace std; typedef long long ll; int T, digits[MAX]; ll N, dp[MAX][2]; ll dfs(int pos, int sta, bool islimit) { if (pos == 0) return 1; if (!islimit && dp[pos][sta] != -1) return dp[pos][sta]; int up = islimit ? digits[pos] : 9; ll cnt = 0; for (int i = 0; i <= up; ++i) { if (sta && i == 9) continue; cnt += dfs(pos - 1, i == 4, islimit && i == digits[pos]); } if (!islimit) dp[pos][sta] = cnt; return cnt; } ll solve(ll num) { int pos = 0; while (num) { digits[++pos] = num % 10; num /= 10; } return dfs(pos, 0, true); } int main(void) { memset(dp, -1, sizeof(dp)); scanf("%d", &T); for (int t = 1; t <= T; ++t) { scanf("%lld", &N); printf("%lld\n", N - solve(N) + 1); } return 0; }
|