数位DP

数位DP

DFS 套路题(hin恶心)

数位dp

经典的数位Dp是要求统计符合限制的数字的个数。

一般的形式是:求区间[n,m]满足限制f(1)、 f(2)、 f(3)等等的数字的数量是
多少。 条件 f(i) 一般与数的大小无关,而与数的组成有关。

善用不同进制来处理,一般问题都是10进制和二进制的数位dp

数位dp的部分一般都是很套路的,但是有些题目在数位dp外面套了一个
华丽的外衣,有时我们难以看出来。 

 

我没做的例题: (浏览一下好啦,主要是看看下面这个模板)

 

 

 

>HDU3652
统计区间 [1,n] 中含有 '13' 且模 13 为 的数字有多少个。
◦ N<=10^9 

>Solution

991366含13    9915366不含

HDU3652简化版
暴力的去枚举每一个数然后去计算必然太慢。
我们先来考虑一个更简单的形式
统计区间 [1,n] 中含有 '3' 的数字有多少个。 

 

◦ N=x_1 x_2 x_3 x_4….. x_total 。 x_in的从高到低第i位是多少。 Total是总
的位数。
◦ 如果我们考虑从高到低位不断填数y_1 y_2 …。那么问题其实就是问有多
少填数的方案,一要满足上限的限制(对应区间[1,n]),二要满足题目
的其他限制。
◦ 这样其实就比[1,n]看起来更能dp了。 

假设到了第ky_k!=x_k,则k位之后就没有上限的限制了,情况就简化了。
如果前面y中没有出现3:那么假如我们可以求出来, f[k][0]表示k位之后没
有上限限制(随意填),但是必须填个3(前面没有出现),有多少种填
数的方案。
如果前面y中出现了3:那么假如我们可以求出来, f[k][1]表示k位之后没有
上限限制(随意填),没有必须出现3的限制(前面出现过了),有多少
种填数的方案。 

 

首先我们可以枚举到哪一位y_k!=x_k,然后再枚举这一位是多少,把对应
F加起来就是答案了,一共需要加 位数*10 次。这运算次数是不大的。
f数组总大小也很小, 位数*2

边界 f[total+1][0]=0,f[total+1][1]=1,转移复杂度O(10)
总复杂度 

 

那回归到原题呢?
枚举哪一位不同没什么变化吧,跟原先一样枚举就好了。
就是f数组要变,因为约束条件更多了,所以状态的维数要增加。
f[k][前面是否已经出现13][上一位是否是1][前面的那些数mod13等于多
],转移的话同样还是枚举这一位是填什么即可。 

 


>那这些是不是大家也都会做了呢!

写写方程捋一下思路。
◦ 1:统计区间 [m,n] 47不能同时出现的数字有多少个?
◦ 2:给你一个区间[n,m],要你求区间内不含“62”“4”的数字的个数?
◦ 3: bzoj1026: windy定义了一种windy数。 不含前导零相邻两个数字
之差至少为2的正整数被称为windy数。 windy想知道,在AB之间,包
AB,总共有多少个windy数? 

>记忆化搜索来实现

其实,我们刚刚那个dp的过程自然是思路很清晰,但是一般实现我们不
那么写。因为毕竟还是好多个for循环,预处理一套循环,算答案一套循
环,记忆话搜索的话则是要什么算什么,会好写很多。
实际上数位dp往往都是用记忆化搜索的方式来实现,就是求什么调用什
么,调用完了,记下来,下次就不用重新算了。
我们来看一下上一题的代码 

◦  表示到了第几位。
◦ State:上一位是否为1
◦ Have:是否已经有13.
◦ K:已经加上的数mod13的值
注意只有不顶到上界才能记忆化下来答案。 


 

关于数位dp的经验

◦ 1:注意很多时候带进去是n==0要特殊处理。
◦ 2:还有一般问[m,n],我们求[1,n]-[1,m-1]但是有的时候m0就炸了。 然
后一道题wa一个小时。。。。。。正常。。。。。
◦ 3:求所有包含49的数,其实就是(总数-所有不包含49的数)。前者的化
需要有两维限制,一个是上一位是什么,一个是之前有没有49。但是后
者只需要记一个上一位是什么。就能好写一些。
◦ 4:一般问题的数位dp部分,都是套路,但是这并不代表它外面“华丽的
外衣”和与其他算法结合的的部分也是无脑的。 要看出它是考数位dp
要看出问题怎么变化一下就是数位dp了。

◦ 5: dp初始化memset要置为-1。不能置为0!!!!!!因为有很多时候
dp值就应该是0,然后我们如果误以为是因为之前没有计算,从新计算的
话,就会tle

这里不能写成0
◦ 6:既然是记忆化搜索,那就可以剪枝!!!!可行性剪枝!!
◦ 7:注意windy数的情况,有时前导0也需要记的!!! 

 

>hdu3079
题中平衡数的定义: 以一个位置作为平衡轴,然后左右其他数字本身大
小作为重量,到平衡轴的距离作为权值,实现左右平衡(即杠杆原理平
衡)。然后为区间[x,y]内平衡数的个数。 (0 ≤ x ≤ y ≤ 1018

>Solution

数位dp当然可以和各种算法套起来。
这题就是典型的 枚举+数位dp。 

首先,感觉这道题如果记录 当前位、选没选平衡轴、当前左边平衡杆权
值减右边平衡杆权值,这样感觉并不好转移。而分析题目性质可以发现,
一个非0数只能会有一个(一一对应) 平衡轴(0除外,最后特殊处理一
下就好),那么如果数位dp外面枚举平衡轴的话,只需计算到最后差是
否为0就好。因为每一种中心轴对应的合法集合互不相交
注意0的特殊情况:就是0被统计了位数次,减掉即可。

 

 

我做了的例题:

>P2657 [SCOI2009]windy数     

   

>P4317 花神的数论题bzoj3209)    

   

>P4124 [CQOI2016]手机号码bzoj4521)    

 

>P2602 [ZJOI2010]数字计数&P4999 烦人的数学作业 

  
 

 

总结

 

posted @ 2019-09-05 17:37  晔子  阅读(246)  评论(0编辑  收藏  举报