1 条题解
-
0
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define LL long long // 修改为long long类型 LL dp[15][15][2]; // dp[pos][pre_zero][limit] int digit[15]; // 记忆化搜索数位DP LL dfs(int pos, int pre_zero, int limit) { if (pos == -1) return 0; // 前导零不计数 if (!limit && !pre_zero && dp[pos][0][0] != -1) return dp[pos][0][0]; if (!limit && pre_zero && dp[pos][1][0] != -1) return dp[pos][1][0]; int up = limit ? digit[pos] : 9; LL res = 0; for (int i = 0; i <= up; i++) { int new_limit = limit && (i == up); int new_pre_zero = pre_zero && (i == 0); if (new_pre_zero) { res += dfs(pos - 1, new_pre_zero, new_limit); } else { res += dfs(pos - 1, new_pre_zero, new_limit); if (i == 0) res += 1; // 当前位是0则计数 } } if (!limit) { if (pre_zero) dp[pos][1][0] = res; else dp[pos][0][0] = res; } return res; } // 计算0到x中0的个数 LL solve(LL x) { if (x < 0) return 0; int pos = 0; while (x) { digit[pos++] = x % 10; x /= 10; } memset(dp, -1, sizeof(dp)); return dfs(pos - 1, 1, 1); } int main() { LL m, n; while (scanf("%lld %lld", &m, &n) != EOF) { // 修改输入格式说明符 if (m == -1 && n == -1) break; LL ans = solve(n) - solve(m - 1); printf("%lld\n", ans); // 修改输出格式说明符 } return 0; }
这个问题要求计算从 m 到 n 所有自然数中数字 0 出现的总次数。这是一个典型的数位统计问题,我们可以使用数位动态规划(数位 DP)来高效解决。 解题思路 解决这个问题的核心思路是:
先计算从 0 到 n 中 0 的个数 再计算从 0 到 m-1 中 0 的个数 两者的差值就是从 m 到 n 中 0 的个数
- 1
信息
- ID
- 2287
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者