预警:由于是从$Vergil$学长那里和$Mathison$大神那里学来的,所以清一色记忆化搜索!qwq

巨佬的数位dp讲解(未来的咕咕日报头条):

https://www.luogu.org/blog/virus2017/shuweidp


数位dp嘛,顾名思义...就是与每个数上的那位有关系...(废话)

一般问题形式都是,在区间$[l,r]$中,满足xx条件的数有多少。然后数据范围一般巨大,枚举是不可能的,这辈子是不可能的。所以一般我们都把它当做字符串处理,预处理出每一位的数(数位),即之后的$border$数组。先求出1~r内满足范围的数,在求出1~l-1范围内的数,运用前缀和的思想一减的。

关于处理成字符串:

一种高精处理方法

        scanf("%s",p+1);int lenp=strlen(p+1);int last=lenp;while(p[last]=='0'&&last) last--;for(int i=last+1;i<=lenp;i++) p[i]='9';p[last]--;for(int i=1;i<=lenp;i++) a[lenp-i+1]=p[i]-'0';memset(dp,-1,sizeof(dp));ans1=dfs(lenp,0,1);scanf("%s",q+1);int lenq=strlen(q+1);for(int i=1;i<=lenq;i++) a[lenq-i+1]=q[i]-'0';memset(dp,-1,sizeof(dp));ans2=dfs(lenq,0,1);printf("%d\n",ans2-ans1);

另一种暴力搞,longlong范围内才可。

        l--;while(l){border[++len]=l%10;l/=10;    }memset(dp,-1,sizeof(dp));ans1=dfs(len,0,1);len=0;while(r){border[++len]=r%10;r/=10;}memset(dp,-1,sizeof(dp));ans2=dfs(len,0,1);len=0;printf("%lld\n",ans2-ans1);


记忆化搜索?其实感觉他是dp的本质吧...(说错了不要打我啊qwq)。搜索我们要遍历所有状态,遍历完就溜,啥也不记下来,没心没肺;dp我们也要遍历全部状态,但是长心眼了,懂得存起来,用空间换时间;然后dp是和记忆化搜索学的,所以记忆化搜索也记录了搜过的状态,当现在搜的之前搜过,就直接调用之前的结果。Update:Vergil学长表示他认为dp的本质是最短路 把各状态当作图的节点,然后与开始节点连的边为初始值...


既然我们记搜了,那么肯定我们需要知道每次记录哪些量:一般地,我们会记到$pos$(现在在第几位,个人习惯从右往左为第1位到第$len$位)、$pre$(上一位是哪个数字,用于与上一位有关的情况)、$ling$前导零标记、$limit$最高位标记、$st$是否已经满足要求了,还有其他实际情况需要的。开始从主程序进来的时候,$ling$和$limit$都是1。

图自@Mathison真·大神

另外,当$limit=1$不能记录和调用dp值!当$ling=1$也不能调用记录dp值!


以上是概论,现在分两种题型扯几道例题。

第一种题型:问你数位满足是否有xx数 or 没有xx数

  • 例1 hdu2089不要62

   题目大意:问你$[l,r]$中不含4且不含连续62的数的个数。

   真·入门题。因为不含,所以只要有4或62连续,之后我们就不用搜了。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4
 5 using namespace std;
 6 typedef long long ll;
 7
 8 int l,r,len;
 9 int border[100];
10 ll ans1,ans2,dp[10][12];
11
12 ll dfs(int pos,int pre,int limit)
13 {
14     if(pos<1) return 1;
15     if(!limit && dp[pos][pre]!=-1) return dp[pos][pre];
16     ll tmp=0;
17     ll lim=limit ? border[pos] : 9;
18     for(int i=0;i<=lim;i++)
19     {
20         if(i==4) continue;
21         if(i==2&&pre==6) continue;
22         tmp+=dfs(pos-1,i,(limit&&i==lim));
23     }
24     if(!limit) dp[pos][pre]=tmp;
25     return tmp;
26 }
27
28 int main()
29 {
30     while(scanf("%d%d",&l,&r)!=EOF&&l!=0&&r!=0)
31     {
32         l--;
33         while(l)
34         {
35             border[++len]=l%10;
36             l/=10;
37         }
38         memset(dp,-1,sizeof(dp));
39         ans1=dfs(len,0,1);
40         len=0;
41
42         while(r)
43         {
44             border[++len]=r%10;
45             r/=10;
46         }
47         memset(dp,-1,sizeof(dp));
48         ans2=dfs(len,0,1);
49         len=0;
50         printf("%lld\n",ans2-ans1);
51     }
52     return 0;
53 }

View Code

  • 例2 hdu3555Bomb

   题目大意:问你1~n中含连续49的数的个数。

   数位dp入门题。因为题目问的是“含”,所以我们必须记一个$st$,看之前是否满足。这里就不能像上一道题一样不满足直接$continue$掉了。因为之后还有希望满足啊qwq。

 1 //求1~n 含有连续49的数字有多少
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5
 6 using namespace std;
 7 typedef long long ll;
 8
 9 int T,len;
10 int border[200];
11 ll dp[200][13][5];
12 char sta[200];
13
14 ll dfs(int pos,int pre,int st,int limit)
15 {
16     if(pos<1) return st;
17     if(!limit && dp[pos][pre][st]!=-1) return dp[pos][pre][st];
18     ll tmp=0;
19     ll lim=limit ? border[pos] : 9;
20     for(int i=0;i<=lim;i++)
21         tmp+=dfs(pos-1,i,st||(i==9&&pre==4),limit&&i==lim);
22     if(!limit) dp[pos][pre][st]=tmp;
23     return tmp;
24 }
25
26 int main()
27 {
28     scanf("%d",&T);
29     while(T--)
30     {
31         scanf("%s",sta+1);
32         len=strlen(sta+1);
33         for(int i=1;i<=len;i++)
34             border[i]=sta[len-i+1]-'0';
35         memset(dp,-1,sizeof(dp));
36         printf("%lld\n",dfs(len,0,0,1));
37     }
38     return 0;
39 } 

View Code

  • 例3 poj3208 Apocalypse Someday

第2种题型:问你数位是否满足一些比较复杂的要求(就不是上面那么简单了)

  • 例1 [SCOI2009]Windy数
  • 例2 [ZJOI2010]数字计数
  • 例3 LuoguP3413萌数
  • 例4 hihocoder#1791幸运数字
  • 例5 bzoj1799[AHOI2009]同类分布
  • 例6 某qbxt测试题

例题会尽量都补上的qwq

关于输出方案:本来想试着输出下方案的,后来发现实际输出的时候其实会少很多。因为我们记忆化!当一个状态下的值已经确定了,我们就不再切身实际地搜,而是直接调用之前结果了,也就方案会少输出了。当然,没记忆化的时候,显然我们可以输出全部方案。

数位dp。。。按Mathison大佬的话,还是非常套路模板化的,唯一要注意的是举一反三和前导零的处理...。

转载于:https://www.cnblogs.com/nopartyfoucaodong/p/9787923.html

数位dp真·浅谈 By cellur925相关推荐

  1. 真·浅谈System.setOut()

    java中我们熟悉的输出System.out.println()只能将数据输出到控制台上,那么我们像要将数据输出到背的地方时该怎么办? System.setOut()来了. System.out是 S ...

  2. 浅谈单调队列优化的DP

    为什么都是浅谈?深入就掉坑啊,掉坑就要填坑啊,填坑就会发现又挖了更多的坑啊,然后恶性循环啊. 这个坑必须要填的,拖了这么久了. 先拿TYVJ 1305来说吧,此题具体的题面没找到,代码简单的对拍了一下 ...

  3. java学习方法-浅谈软件开发的神速进步

    中国人大都喜欢用武侠小说来比较软件开发,但是在实战武功中,只有葵花宝典才是最厉害的,也只有掌握了葵花宝典,才能称为"不败". 1浅谈软件开发的神速进步 1.1什么才是软件开发的葵花 ...

  4. Ybtoj 最优密码 单调队列(浅谈)树状数组 两种解法

    作者:hsez_yyh 链接:https://blog.csdn.net/yyh_getAC/article/details/123956399  来源:湖北省黄石二中竞赛组  著作权归作者所有.商业 ...

  5. 浅谈GCC预编译头技术

    浅谈GCC预编译头技术 文/jorge --谨以此文,悼念我等待MinGW编译时逝去的那些时间. 其 实刚开始编程的时候,我是丝毫不重视编译速度之类的问题的,原因很简单,因为那时我用BASICA.后来 ...

  6. 大红灯笼高高挂专业影评_浅谈《大红灯笼高高挂》

    初来乍到,浅知拙见,万望海涵. 利用闲暇时间第一次完整地看完了<大红灯笼高高挂>的电影(没有看原著),终于能从身边各种声音中辨出一二,进而斗胆在这里发出属于自己的声音.在这里从两个方面浅谈 ...

  7. 浅谈代码的执行效率(4):汇编优化

    终于谈到这个话题了,首先声明我不是汇编优化的高手,甚至于我知道的所有关于汇编优化的内容,仅仅来自于学校的课程.书本及当年做过的一些简单练习.换句话说,我了解的东西只能算是一些原则,甚至也有一些&quo ...

  8. 数位dp 的简单入门

    时间紧张,就不讲那么详细了. 之前一直被深搜代码误解,以为数位dp 其实就是记忆化深搜...(虽说爆搜确实很舒服而且还好想) 但是后来发现数位dp 的标准格式其实是 预处理 + dp ...... 数 ...

  9. [原创] 浅谈ETL系统架构如何测试?

    [原创] 浅谈ETL系统架构如何测试? 来新公司已入职3个月时间,由于公司所处于互联网基金行业,基金天然固有特点,基金业务复杂,基金数据信息众多,基金经理众多等,所以大家可想一下,基民要想赚钱真不容易 ...

最新文章

  1. 机器视觉检测中的图像预处理方法
  2. Linux文件查找工具的探索
  3. 从我开始学单片机到完成一个智能小车的制作我都需要掌握哪些知识?
  4. 鱼缸式百分比信息图表,这样计算才正确
  5. 只需几步,U盘就能变“光驱”
  6. android studio 的AVD Manager点击无响应解决办法
  7. html如何让条数按序号输出,JS 怎么控制页面序号较智能的生成?
  8. 湖南大学计算机考研考什么,2017年湖南大学计算机系统考研大纲
  9. HH SaaS电商系统的物流单设计
  10. 从前世今生聊一聊,大厂为啥亲睐时序数据库
  11. swing学习一(swing介绍、swing样例、布局管理器)
  12. IT专业沦为新时代农民工?为什么你身边的人都不让你报计算机专业?
  13. 硬件升级win8.1重新安装系统
  14. 太不可思议了,竟然用交通锥当 logo!
  15. VirtualBox下配置 Ubantu18.4 总纲领
  16. 【Unity3D】制作进度条——让Image同时具有Filled和Sliced的功能
  17. Eventloop事件循环机制
  18. 微信7.0.10内测更新!除了适配暗黑模式,还有这些实用功能!
  19. EMC-传导发射的共模和差模噪声的有效处理方案
  20. Jmeter接口测试实例讲解

热门文章

  1. 教你如何制作浪漫的3D相册表白网站 HTML+CSS+JavaScript
  2. QIIME 2:可重复、交互和扩展的微生物组数据分析流程
  3. 使用XML表达表格数据
  4. 服务器漏洞--永恒之蓝
  5. Python OpenCV --Drowsiness Detector 睡意检测--项目记录
  6. postgresql主从复制、主从切换
  7. AI考拉技术分享会—手把手教你入门UI 自动化测试 Appium
  8. 企业视频直播平台有哪些呢
  9. JavaScript window.alert
  10. layui文件上传后台(带自定参数)