初探数位dp

  前言:这是蒟蒻第一次写算法系列,请诸位大佬原谅文笔与排版。



一、导入

  在刷题的时候,我们有时会见到这样一类问题:在区间$[l,r]$内,共有多少个整数满足某种条件。如果$l$和$r$间的差很小,我们可以考虑暴力枚举直接判断。然而,若$l<=r<=10^9$甚至更大呢?

  这时往往就可以用到一种dp方式:数位dp。



二、做法:

  这里先放一道例题:1026: [SCOI2009]windy数

  题意:求在区间$[l,r]$内,满足相邻数位的差>=2的整数的个数。

  首先我们可以发现,$[l,r]$的答案=$[1,r]$的答案-$[1,l)$的答案。于是我们可以把问题转化为求$[1,r]$和$[1,l-1]$的答案。因为$l<=r<=2*10^9$,所以暴力枚举肯定行不通。但是我们可以发现这道题中整数需满足的条件只与相邻数位有关,这启示我们,也许可以按位dp?

  我们先来看一张经典的图(表示区间$[0,22]$):

  

  这幅图中把正整数按位用树的形式表示,那么区间$[0,x]$(这里x=22)就可以拆成多棵满10叉树(即图中的蓝圈),而且因为每层所用的树个数不会超过10棵(0~9),总共有$\log_{10}{x}$层,则树的个数规模为$O(10\log{x})$。

  那么单棵满10叉树的答案怎么求呢?我们仔细观察这棵树,那么就可以发现每棵满10叉树表示的数是位数相同(等于它从下往上数所处的层数),最高位相同(等于根节点表示的数),且该树的答案只与以树根的10个儿子为根的,10棵子树的答案有关。并且在整棵树中,处在同一层的,且子树根节点表示的数相同的树(即位数相同,最高位相同),它们是等价的。于是我们就可以直接设$f[i][j]$表示有i位,最高位为j的满足条件的整数的个数,然后xjb转移。于是就可以优哉游哉地dp, 然后按图统计答案了。

  不过这道题还是比较麻烦,因为需要排除前导零的影响,不过核心思想还是上面的那样,然后再分位数统计就好了。

  代码(时间复杂度$O(10^2\log{r})$):

bzoj1026



三、归纳:

  数位dp的特征:数据规模大,统计整数个数,被统计的数满足的条件往往与数位之间的关系或数位间的运算有关。

  基本做法:差分,先按位dp出所需数据($f[i][S]$->i位数,状态为S),然后再拆分原区间,用dp出的数据统计。



四、其他例题:

  to be continued……(以后吧。。。)

原文地址:https://www.cnblogs.com/quzhizhou/p/9245648.html

时间: 2024-10-19 11:08:45

初探数位dp的相关文章

数位dp初探

我这种蒟蒻就一直不会写数位dp.. 于是开了个坑.. 1833: [ZJOI2010]count 数字计数 这道被KPM大爷说是入门题..嗯似乎找找规律然后减掉0的情况后乱搞就可以了..(但是还是写了很久TAT #include<cstring> #include<iostream> #include<cstdio> #include<queue> #include<cmath> #include<algorithm> #define

数位类统计问题--数位DP

有一类与数位有关的区间统计问题.这类问题往往具有比较浓厚的数学味道,无法暴力求解,需要在数位上进行递推等操作.这类问题往往需要一些预处理,这就用到了数位DP. 本文地址:http://www.cnblogs.com/archimedes/p/numerical-digit-dp.html,转载请注明源地址. 基础知识 [l,r] 意为 l<=且<=r的数 [l,r) 意为 l<=且< r的数 (l,r] 意为 l<且<=r的数 (l,r) 意为 l<且< r

51Nod 1009 数字1的个数 | 数位DP

题意: 小于等于n的所有数中1的出现次数 分析: 数位DP 预处理dp[i][j]存 从1~以j开头的i位数中有几个1,那么转移方程为: if(j == 1) dp[i][j] = dp[i-1][9]*2+pow(10,i-1);else dp[i][j] = dp[i-1][9]+dp[i][j-1]; 然后注意下对于每个询问统计的时候如果当前位为1需要额外加上他后面所有位数的个数,就是n%pow(10,i-1); 这样总复杂度log(n)*10 #include <bits/stdc++.

HDU 3555 Bomb (数位DP)

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数,它是按位来进行计数统计的,可以保存子状态,速度较快.数位dp做多了后,套路基本上都差不多,关键把要保存的状态给抽象出来,保存下来. 简介: 顾名思义,所谓的数位DP就是按照数字的个,十,百,千--位数进行的DP.数位DP的题目有着非常明显的性质: 询问[l,r]的区间内,有多少的数字满足某个性质 做法根据前缀和的思想,求出[0,l-1]和[0,r]中满足性质的数的个数,然后相减即可. 算法核心: 关于数位DP,貌似写法还是

51nod1043(数位dp)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1043 题意:中文题诶- 思路:数位dp 我们用dp[i][j]来存储长度为2*i且一半和为j的所有情况(包括前导0的情况),为了方便我们现在只讨论其一半的和的情况,因为如果包括前导0的话其两边的情况是一样的: 我们假设再长度为i-1的数字最前面加1位数字k,0<=k<=9(这位数字加在哪里并不影响答案,因为我们在计算i-1长度的时候已经计算了所有组合情况,

数位dp

1.[hdu3709]Balanced Number 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cstdlib> 6 #include<algorithm> 7 #include<ctime> 8 #include<cmath> 9 #include<queue>

【HDU 3652】 B-number (数位DP)

B-number Problem Description A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string "13" and can be divided by 13. For example, 130 and 2613 are wqb-numbers, but 143 and 2639 are not. Your task

hdu 5898 odd-even number 数位DP

odd-even number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 716    Accepted Submission(s): 385 Problem Description For a number,if the length of continuous odd digits is even and the length

LightOJ1068 Investigation(数位DP)

这题要求区间有多少个模K且各位数之和模K都等于0的数字. 注意到[1,231]这些数最大的各位数之和不会超过90左右,而如果K大于90那么模K的结果肯定不是0,因此K大于90就没有解. 考虑到数据规模,数据组数,这题状态这么表示: dp[i][j][k]:位数为i模K结果为j且各位数之和模K结果为k的数字个数 然后就是转移方程,最后就是统计.. 统计部分好棘手...半乱搞下AC的..还是对数位DP的这一部分太不熟悉了. 1 #include<cstdio> 2 #include<cstr