例题: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, 999
abc
1. num[i] < x, 0
2. num[i] == x, 0~efg
3. 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;
}