#sWDPybttg050302. 1586:【 例 2】数字游戏
1586:【 例 2】数字游戏
好的,我将这道题整理为清晰的题面格式,并补充样例解释、数据范围与时空限制:
题目描述
科协里最近很流行数字游戏。某人命名了一种不降数,这种数字必须满足从左到右各位数字成小于等于的关系,如 ,。现在大家决定玩一个游戏,指定一个整数闭区间 ,问这个区间内有多少个不降数。
输入格式
有多组测试数据。每组只含两个整数 ,意义如题目描述。
输入以文件结束(EOF)为终止。
输出格式
对于每组测试数据,输出一行一个整数,表示 之间不降数的个数。
样例
样例输入
1 9
1 19
样例输出
9
18
样例解释
第一组:,所有一位数 都是不降数(因为没有更低的位比较),共 个。
第二组::
- 一位数:,共 个;
- 两位数不降数:?
但 以内只有:,共 个。
所以总不降数 个。
注意 不是不降数(),所以不在内。
数据范围
对于全部数据,。
时空限制
- 时间:
- 内存:
提示
此题为 数位 DP 经典题。
状态设计: 表示当前处理到第 位(从高位到低位),上一位数字是 时,满足不降数条件的数的个数。
转移:当前位 必须 ,枚举 从 到 。
但这里需要注意,当 初值为 (表示前面没有数字),则当前位可以从 开始(因为不能有前导零?实际上对于位数不足的情况,前导零不影响大小,但在比较时需要特殊处理:如果前面都是前导零,则当前位可以从 开始,但一旦开始填非零数字,就不能再填比它小的数字?实际上更简单的办法是:允许前导零存在,但在最终数中前导零不视为数字,所以当 last=0 且当前位填 0 时,last 仍为 0,继续传递)。
因此状态可设为 ,其中 表示是否前面全是前导零。
简化做法:
由于不降数要求数字非降,我们可以直接枚举数字长度 ,然后从 中选 个数字(可重复,但必须非降),这就是组合数问题。但因为有前导零的存在(即实际位数可能小于 ),需要小心处理。
更通用的数位 DP 方法:
- 将数字 拆分成数位数组 ;
- DFS(pos, last, limit, lead):
- pos:当前处理到的位;
- last:上一位填的数字(若无上一位则设为 0);
- limit:是否受到 的限制;
- lead:是否前面全是 0。
- 记忆化:dp[pos][last][lead],limit 不记忆(因为 limit 为 1 的状态只对应一种情况)。
- 转移:枚举当前位数字 从 (lead ? 0 : last) 到 (limit ? digits[pos] : 9),且必须满足 或 lead 为真(即前面全 0 时可以任意开始)。
最终答案为:dfs(0, 0, true, true)。
复杂度:状态数 ,可以很快。
注意:数字 是否算不降数? 是一位数,且满足不降,但题目区间从 开始,所以不影响。若区间包含 ,需单独考虑。