0%

1742. 盒子中小球的最大数量

1742.盒子中小球的最大数量

题目描述:

你在一家生产小球的玩具厂工作,有 n 个小球,编号从 lowLimit 开始,到 highLimit 结束(包括 lowLimithighLimit ,即 n == highLimit - lowLimit + 1)。另有无限数量的盒子,编号从 1infinity

你的工作是将每个小球放入盒子中,其中盒子的编号应当等于小球编号上每位数字的和。例如,编号 321 的小球应当放入编号 3 + 2 + 1 = 6 的盒子,而编号 10 的小球应当放入编号 1 + 0 = 1 的盒子。

给你两个整数 lowLimithighLimit ,返回放有最多小球的盒子中的小球数量如果有多个盒子都满足放有最多小球,只需返回其中任一盒子的小球数量。

数据范围:

$1\le lowLimit \le highLimit \le 10^5$

题解:

数位dp的话,可以求编号不超过多少的个位。这里需要求不超过上界,并且数位和为 $target$ 的个数。

因此需要求数位和为 $[1, 45]$ 所有 $target$ 的个数。每个都是需要前缀差。

代码:

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
48
49
auto optimize_cpp_stdio = []()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
class Solution
{
public:
const static int maxn = 1e5 + 10;
const static int maxm = 1e5 + 10;
const int INF = 0x3f3f3f3f;
string s;
int len;
int dp[5][45];
int dfs(int step, int val, int target, bool isLimit)
{
if(step == len)
return val == target;
if(!isLimit && dp[step][val] != -1)
return dp[step][val];
int up = isLimit ? s[step] - '0' : 9;
int ans = 0;
for (int i = 0; i <= up; ++i)
{
ans += dfs(step + 1, val + i, target, isLimit && i == up);
}
if(!isLimit)
dp[step][val] = ans;
return ans;
}
int solve(int upper, int target)
{
memset(dp, -1, sizeof(dp));
s = to_string(upper);
len = s.length();
return dfs(0, 0, target, true);
}
int countBalls(int lowLimit, int highLimit)
{
int maxx = 0;
for (int i = 1; i <= 45; ++i)
{
maxx = max(maxx, solve(highLimit, i) - solve(lowLimit - 1, i));
}
return maxx;
}
};