数位dp例题

在了解数位dp之前,先来看一个问题:

求a~b中不包含49的数的个数. 0 < a、b < 2*10^9;

注意到n的数据范围非常大,暴力求解是不可能的,考虑dp,如果直接记录下数字,数组会开不起,该怎么办呢?要用到数位dp.

数位dp一般应用于:求出在给定区间[A,B]内,符合条件P(i)的数i的个数. 条件P(i)一般与数的大小无关,而与 数的组成 有关.

这样,我们就要考虑一些特殊的记录方法来做这道题.一般来说,要保存给定数的每个位置的数.然后要记录的状态为当前操作数的位数,剩下的就是根据题目的需要来记录.可以发现,数位dp的题做法一般都差不多,只是定义状态的不同罢了.

总结:

         1.如果题目中出现求满足区间[l,r]的符合......性质的数的个数,考虑使用数位dp.

         2.思考一下:如果我们只能从前往后一位位枚举当前的数位,要做出这道题,我们需要知道哪些量?利用这些来补充到dfs的调用参数中.

         3.套用模板.

HDU  2089 不要62

题意:给个区间l,r求区间内没有62,并且没有4的数的个数

思路:数位dp模板题目,dp[i][0]表示长度为i,且第i+1位不为6的所有符合条件的数 ,dp[i][1]表示长度为i,且第i+1位为6的所有符合条件的数,

HDU  3652 B-number

题意:给一个数n,求前n个数 有多少个数 那个数%13==0 且那个数包括子串13

思路:dp[i][j][0]表示长度为i,第i位前面的数位和取模13为j,且 第i位前面的数位不含13
dp[i][j][1]表示长度为i,第i位前面的数位和取模13为j,且 (长度为i+1那位)第i+1位为1 
dp[i][j][0]表示长度为i,第i位前面的数位和取模13为j,且 第i位前面的数位不含13

当p等于0时  只有mod==0&&sta==2才可以返回1,长度为p的某种状态只要加上所有长度为p-1的所有状态,就是长度为p的状态的数量;

POJ  3252 Round Numbers

题意:给l,r,求区间l,r中的数,二进制表示时0的个数大于等于1的个数

思路:dp[i][j]表示长度为i(二进制表示的),第i位前面的数位0的数量-数位1的数量为j;但是如果有前导0的话,长度变化时dfs的状态是一样的,所以除了limit标志以为再加一个前导0标志,然后分情况进行状态转移;

HDU  4734 F(x)

题意:定义f(x) = a(n)*2^(n-1)+a(n-1)*2(n-2)+…a(2)*2+a(1)*1,a(i)表示十进制数x中第i位的数字。 
题目给出a,b,求出0~b有多少个不大于f(a)的数。

思路:看到这个题目,马上想到的思路就是dp[i][j]表示长度为i,第i位前面的权值和为j的合法方法数,当p==0时,权值小于f(a)时返回1,但是,f(a)每次都在变,也就是说dp数组每输入一个a,b就要初始化,memset超时,这样就想到优化,优化成只要初始化一次dp数组,优化的思路就是当p==0时返回1的条件不能与f(a)有关,这样可以设计dp数组dp[i][j]表示长度为i,第i位前面的权值和小于等于j的符合条件的数的数量,递归的时候求小于等于f(a)的数量,当p等于0时,判断递归的权值是否大于等于0即可;

HDU  3709 Balanced Number

题意:求区间内平衡数的个数,  平衡数定义为 一个数以某一个数位为支点,左边数位上的数*到支点距离等于右边数位上的数*到支点的距离 比如  3218就是一个以1为支点的平衡数  2*1+3*2==8*1

思路:这个题目和上面所有题目不同的地方就是要枚举支点,dp[p][pos][sum] 表示长度为p,以pos为支点,第p为前面的权值和为sum(sum是以pos为支点,数位*距离的和),状态转移就是 dp[p][pos][sum]+=dp[p-1][pos][sum+(p-pos)]最后如果p==0时sum==0就返回1  注意最后还要减去0的个数,因为0不管是以哪一位做支点都重复算了一次,其他数显然不可能重复计算;

SPOJ  BALNUM Balanced Numbers

题意:平衡数定义:一个数的数位出现过的数字,如果是偶数,总出现次数要是奇数次,如果是奇数,出现的次数要是偶数次,注意,不要看成所有奇数出现次数为偶数,所有偶数出现次数为奇数,

思路:dp[i][1<<10][1<<10]  状压一下,两个状态,第一个状态i位上表示第i个数出现的次数是奇数次1,还是偶数次0,第二个状态i位上表示的是i这个数字有没有出现过,出现1,没出现0,然后注意一下前导0就OK了。特别注意一些为运算的优先级呀!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值