1 solutions
-
2
数位DP的递推模板:
- 给足维度,定义状态,用DP预处理;
- 先求区间
[0或1, L – 1]
内满足条件的数:把L拆位,然后从高到低依次处理; - 同样的方法处理区间
[0, R]
; - 利用前缀和思想,
solve(R) – solve(L–1)
即为答案。
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int N = 35; int a, b; // f[i][j]:i位数,以j开头的不降数个数 int f[N][10]; void init() { for (int i = 0; i <= 9; i++) f[1][i] = 1; for (int i = 2; i < N; i++) for (int j = 0; j <= 9; j++) for (int k = j; k <= 9; k++) f[i][j] += f[i - 1][k]; } int num[N]; LL solve(int x) { if (!x) return 1; // 拆位 int len = 0; while (x) { num[++len] = x % 10; x /= 10; } // 记录(从左到右)上一位的数字,因为要保证数字不降 int last = 0; LL ans = 0; for (int i = len; i >= 1; i--) { int now = num[i]; for (int j = last; j < now; j++) ans += f[i][j]; // 当前位大于上一位,后续不可能再有不降数了 if (last > now) break; last = now; // 数位DP需要注意的点:边界值如果符合要求,也要加上! if (i == 1) ans++; } return ans; } int main() { init(); while (cin >> a >> b) { // cout << solve(b) << ' '; // cout << solve(a - 1) << '\n'; cout << (solve(b) - solve(a - 1)) << '\n'; } return 0; }
- 1
Information
- ID
- 166
- Time
- 1000ms
- Memory
- 512MiB
- Difficulty
- 7
- Tags
- # Submissions
- 25
- Accepted
- 9
- Uploaded By