文章目录
- 例题:338. 计数问题
- 解法1——转换成1067. 范围内的数字计数,数位DP模板
- 解法2——分情况讨论(TODO,还没理解)
- 相关链接⭐
例题:338. 计数问题
https://www.acwing.com/problem/content/340/
解法1——转换成1067. 范围内的数字计数,数位DP模板
解法来自:【算法】数位DP
import java.util.*;public class Main {static int[][] memo;static char[] s;static int t;public static void main(String[] args){Scanner sc = new Scanner(System.in);while (true) {int a = sc.nextInt(), b = sc.nextInt();if (a == 0 && b == 0) return;for (int i = 0; i <= 9; ++i) {System.out.print((a > b? count(a, i) - count(b, i): count(b, i) - count(a, i)) + " ");}System.out.println();}}// 计算1~n中,数字x出现的次数static int count(int n, int x) {s = Integer.toString(n).toCharArray();t = x;int m = s.length;memo = new int[m][m];for (int i = 0; i < m; ++i) Arrays.fill(memo[i], -1);return dfs(0, true, false, 0);}static int dfs(int i, boolean isLimit, boolean isNum, int cnt) {if (i == s.length) return cnt;if (!isLimit && isNum && memo[i][cnt] != -1) return memo[i][cnt];int res = 0;if (!isNum) res = dfs(i + 1, false, false, 0);int up = isLimit? s[i] - '0': 9;for (int d = isNum? 0: 1; d <= up; ++d) {res += dfs(i + 1, isLimit && d == up, true, cnt + (d == t? 1: 0));}if (!isLimit && isNum) memo[i][cnt] = res;return res;}
}
解法2——分情况讨论(TODO,还没理解)
https://www.acwing.com/video/323/
https://www.acwing.com/activity/content/code/content/64211/
我们需要实现一个函数 count(int n, int x)
求 1 ~ n 中数字 x 出现的次数。
分情况讨论
是思路中最重要的部分。
#include <iostream>
#include <algorithm>
#include <vector>using namespace std;const int N = 10;/*001~abc-1, 999abc1. num[i] < x, 02. num[i] == x, 0~efg3. num[i] > x, 0~999*/int get(vector<int> num, int l, int r)
{int res = 0;for (int i = l; i >= r; i -- ) res = res * 10 + num[i];return res;
}int power10(int x)
{int res = 1;while (x -- ) res *= 10;return res;
}int count(int n, int x)
{if (!n) return 0;vector<int> num;while (n){num.push_back(n % 10);n /= 10;}n = num.size();int res = 0;for (int i = n - 1 - !x; i >= 0; i -- ){if (i < n - 1){res += get(num, n - 1, i + 1) * power10(i);if (!x) res -= power10(i);}if (num[i] == x) res += get(num, i - 1, 0) + 1;else if (num[i] > x) res += power10(i);}return res;
}int main()
{int a, b;while (cin >> a >> b , a){if (a > b) swap(a, b);for (int i = 0; i <= 9; i ++ )cout << count(b, i) - count(a - 1, i) << ' ';cout << endl;}return 0;
}
相关链接⭐
【算法】数位DP