写在开头
本文dp数组基础讲的比较简略,看不懂请另查文章. 求解代码部分比较详细.
这篇写的累死我了(雾
题目
洛谷p2602数字计数https://www.luogu.com.cn/problem/P2602
给定两个正整数 a 和 b,求在 [a,b] 中的所有整数中,每个数码(digit)各出现了多少次。
思路
分别求[0,a]和[0,b]各个数码出现的次数,然后cnt[b] - cnt[a]就行了,这题a,b范围能到10^12^暴力显然超时,因为000-099和100-199和600-699这种后面两位中数码出现的次数是一样的,自然想到DP记录多少位对应多少次
dp预处理
定义
dp[i]定义为i位数的每种数字有多少个(例如dp[2]代表00到99中某个数出现的次数,此处加前导0是为了使0和其他数一样)
一图流
公式
dp[i] = dp[i-1]*10 + 10^i-1^
递推公式是如何推导来的呢?
下面以数字2的出现举几个栗子(定义一下dp[0] = 0)
0到9,2只出现了一次dp[1] = dp[0]*10 + 10^0^
00到99呢, 我们分成两部分
一部分是小一位次数即dp[1]*10(因为0到9是1次, 10到19是一次,一共10次所以乘以10)
另一部分则是当前位次数即10^1^(因为20到29,一共有10^1^次)
所以我们得到了dp[2] = dp[1]*10 + 10^1^
最后看一下000到999
第一部分dp[2]*10(即000到099,100到199直到999一共十次)
第二部分10^2^(即200到299一共100次)
强调一下22是2次,因为题目求的是2出现的次数,不是有2的数字出现的次数
初始化
dp[0] = 0
递推顺序
正序
举例推导
公式部分已有列出(强烈建议看下文的一图流)
细节
数位限制
如23,
01,02,03…09中0出现十次其他0到9的数出现1次
11,12…..19中1出现十次其他0到9的数都1次
21…23
2为数位限制,需特判
前导0
01到99时,01,02这种前面的0是多余的,对0要特判
求解代码
递推
我们先设数字为ABCD
看A000,如果我们要求出它所有数位之和,我们会怎么求?
鉴于我们其实已经求出了0-9,0-99,0-999。。。上所有数字个数(f[i],且没有考虑前导0)我们何不把这个A000看成0000-1000-2000…A000对于不考虑首位每一个式子的数字的出现个数为 A*f[3]。加上首位出现也就是小于A每一个数都出现了10^3次,再加上,我们就把A000处理完了。
这样你以为就把第一位处理完了?不不不,首位A还出现了BCD+1次呢,也就是从A000~ABCD,这个A还出现了BCD+1次,所以再加上这些才行呢。那么你发现,我们成功把首位代表的所有数字个数求出来了,剩下的求解与A完全没有任何关系,只是BCD的求解,于是我们发现我们已经把一个大问题,化成了一个个小问题,也即是,对于一个这样n位的数,把他一位位的分离开来。
当然你还需要处理前导0你会发现前导0一定是0001,0002。。。0012,0013。。。0101,0102.。。0999这样的数,一共出现了10(i-1)+10(i-2)+…10 (i表示数字位数),让0的统计减去这个值,那么恭喜你这道题做完了。
一图流
首先dp预处理,然后我们分别求解a,b的数位出现次数,cnt[b[i]] - cnt[a[i]]就是a到b区间内数位i出现次数
初始化dp代码
1 | void intit(){ |
求解[0,a]的数位出现次数代码(拆数)
1 | void solve(long long a, vector<long long>cnt){ |
记忆化搜索(dfs)
每次查找完某一个数出现的次数
定义
dp[pos] [sum] [lead] [limit]表示限制条件中某数码出现的次数
pos表示最低要求的数前有几位
sum表示要求数开始有几位
如要求2,dp[2] [1] 就是200-299, dp[2] [2] 表示2200-2299
lead表示有无前导0
有为true,否位false
limit代表数位限制
如果能取到0-9取false,不能则取true
一图流(以处理324的2次数为例)
看不懂没关系,跟着下面的代码一步步分析(求0-a的数码次数)
1 | long long dp[n][n][2][2]; |
相关题目
洛谷P4999 烦人的数学作业
难度: 普及+/提高
https://www.luogu.com.cn/problem/P4999
洛谷P2657windy 数
难度: 提高+/省选-
https://www.luogu.com.cn/problem/P2657
p2657的实现(用的记忆化模板)
1 |
|
洛谷P4124 手机号码
难度:提高+/省选-
https://www.luogu.com.cn/problem/P4124
洛谷p4798 卡尔文球锦标赛
难度:省选/NOI-
https://www.luogu.com.cn/problem/P4798
洛谷P3281 数数
难度:省选/NOI-
https://www.luogu.com.cn/problem/P3281
洛谷p2518 计数
难度:省选/NOI-
https://www.luogu.com.cn/problem/P2518
洛谷p3286 方伯伯的商场之旅
难度:省选/NOI-