题目链接

https://www.luogu.org/problemnew/show/P2657

分析

第一道数位DP题,发现有点意思

DP求\([L,R]\)区间内的XXX个数,很套路地想到前缀和,先求\([1,R],[1,L]\)相减就好了

状态转移也明确,发现状态只和上一位数位的数有关,\(f[i][j]\)表示第\(i\)位放\(j\)的话有多少个windy数,注意的这里的windy数是在钦定一个数字最高位是多少情况下所有的windy数的数量和(即[1,i-1]位放数情况都被算了一遍)

\(f[i][j] = f[i-1][ j-2/j+2]\)

然后考虑怎么求答案.

假如我们要求\(1\)到\(R\)中的windy数有多少,设R有x位,第i位数字为num[i]

首先对于位数小于\(x\)的以及第\(x\)位数字小于\(num[x]\)都可以算进去

然后考虑卡到R边界的情况,我们可以枚举前k位卡到了上限即前\(k\)位与R的前\(k\)位相同,那么在第\(k+1\)位进行答案统计

首先我们是不能达到上界的(这样的话可能算多次),在枚举\(k+1\)位的数字为\(d\)时根据定义只有当\(abs(d-a[k])>=2\)时才能累计答案

但是还有一个问题就是你本身枚举与R相等的前k位数可能就违反了windy数的定义,那么我们需要特判一下退出,但是还需要注意由于这个原因我们需要倒序枚举,因为正序枚举的话如果你前面有一对数是非法的,无论后面数位为何值整个数就是非法的

还有一些奇奇怪怪的问题比如前导\(0\).不过这个也挺好想的.

最后发现如果\(R\)也是个windy数的话没判到(我们的卡上界实际上是没有卡到的,我们总是在当前枚举的这一位比R小),所以特判一下就好了

代码

  1. /*
  2. code by RyeCatcher
  3. */
  4. #include <cstdio>
  5. #include <cstdlib>
  6. #include <cstring>
  7. #include <algorithm>
  8. #include <cctype>
  9. #include <utility>
  10. #include <queue>
  11. #include <vector>
  12. #include <ext/pb_ds/hash_policy.hpp>
  13. #include <ext/pb_ds/assoc_container.hpp>
  14. #include <iostream>
  15. #define DEBUG freopen("dat.in","r",stdin);freopen("wa.out","w",stdout);
  16. #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
  17. #define ri register int
  18. #define ll long long
  19. #define ull unsigned long long
  20. #define SIZE 1<<22
  21. using std::min;
  22. using std::max;
  23. using std::priority_queue;
  24. using std::queue;
  25. using std::vector;
  26. using std::pair;
  27. using namespace __gnu_pbds;
  28. inline char gc(){
  29. static char buf[SIZE],*p1=buf,*p2=buf;
  30. return p1==p2&&(p2=(p1=buf)+fread(buf,1,SIZE,stdin),p1==p2)?EOF:*p1++;
  31. }
  32. #define gc getchar
  33. template <class T>inline void read(T &x){
  34. x=0;int ne=0;char c;
  35. while((c=gc())>'9'||c<'0')ne=c=='-';x=c-48;
  36. while((c=gc())>='0'&&c<='9')x=(x<<3)+(x<<1)+c-48;x=ne?-x:x;return ;
  37. }
  38. const int maxn=12;
  39. const int inf=0x7fffffff;
  40. int a,b;
  41. int toa=0,numa[maxn],tob=0,numb[maxn],f[maxn][maxn];
  42. int main(){
  43. int x,y;
  44. read(a),read(b);
  45. for(ri i=0;i<=9;i++)f[1][i]=1;
  46. x=a;
  47. while(x){
  48. numa[++toa]=x%10;
  49. x=x/10;
  50. }
  51. x=b;
  52. while(x){
  53. numb[++tob]=x%10;
  54. x=x/10;
  55. }
  56. bool flag=1;
  57. for(ri i=2;i<=tob;i++)if(abs(numb[i]-numb[i-1])<2){flag=0;break;}
  58. for(ri i=2;i<=tob;i++){
  59. for(ri j=0;j<=9;j++){
  60. for(ri k=0;k<=9;k++){
  61. if(abs(k-j)>=2)f[i][j]+=f[i-1][k];
  62. }
  63. }
  64. }
  65. ll ans=0;
  66. ans+=flag;
  67. for(ri i=1;i<numb[tob];i++)ans+=f[tob][i];
  68. for(ri i=1;i<tob;i++){
  69. for(ri j=1;j<=9;j++)ans+=f[i][j];
  70. }
  71. for(ri i=tob-1;i>=1;i--){
  72. for(ri j=0;j<numb[i];j++){
  73. if(abs(j-numb[i+1])>=2)ans+=f[i][j];
  74. }
  75. if(abs(numb[i]-numb[i+1])<2)break;
  76. }
  77. for(ri i=1;i<numa[toa];i++)ans-=f[toa][i];
  78. for(ri i=1;i<toa;i++){
  79. for(ri j=1;j<=9;j++)ans-=f[i][j];
  80. }
  81. for(ri i=toa-1;i>=1;i--){
  82. for(ri j=0;j<numa[i];j++){
  83. if(abs(j-numa[i+1])>=2)ans-=f[i][j];
  84. }
  85. if(abs(numa[i]-numa[i+1])<2)break;
  86. }
  87. printf("%lld\n",ans);
  88. return 0;
  89. }

luogu2657-Windy数题解--数位DP的更多相关文章

  1. 洛谷P2657 [SCOI2009]windy数 题解 数位DP

    题目链接:https://www.luogu.com.cn/problem/P2657 题目大意:找区间 \([A,B]\) 范围内 不含前导零 且 相邻两个数字之差至少为2 的正整数的个数. 题目分 ...

  2. BZOJ_1026_[SCOI2009]windy数_数位DP

    BZOJ_1026_[SCOI2009]windy数_数位DP 题意:windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之 ...

  3. windy数(简单数位DP)

    1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 6306  Solved: 2810[Submit][Sta ...

  4. bzoj1026: [SCOI2009]windy数(数位dp)

    1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 8203  Solved: 3687[Submit][Sta ...

  5. [bzoj 1026]windy数(数位DP)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1026 分析: 简单的数位DP啦 f[i][j]表示数字有i位,最高位的数值为j的windy数总 ...

  6. bzoj 1026 [SCOI2009]windy数(数位DP)

    1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4550  Solved: 2039[Submit][Sta ...

  7. windy数(数位DP)

    windy数Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:165888KB     64bit I ...

  8. [bzoj1026][SCOI2009]windy数_数位dp

    windy数 bzoj-1026 题目大意:求一段区间中的windy数个数. 注释:如果一个数任意相邻两位的差的绝对值都不小于2,这个数就是windy数,没有前导0.$区间边界<=2\cdot ...

  9. 2018.06.30 BZOJ1026: [SCOI2009]windy数(数位dp)

    1026: [SCOI2009]windy数 Time Limit: 1 Sec Memory Limit: 162 MB Description windy定义了一种windy数.不含前导零且相邻两 ...

  10. 1026. [SCOI2009]windy数【数位DP】

    Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之间,包括A和B,总共有多少个windy数? I ...

随机推荐

  1. 遇到多个构造器参数时要考虑用构建器 builder 模式 JavaBean 线程安全

    effective java p9 JavaBeans模式阻止了把类做成不可变的可能,这需要程序员付出额外的努力来确保它的线程安全.

  2. vue 实现返回上一页不请求数据keep-alive

    常规操作: 我们通常会将通过接口请求数据的方法放在==created== 或者 ==mounted==这两个生命周期中的一个里面调用. 但是我们知道,不管是我们刚进入这个页面还是从其他页面返回这个页面 ...

  3. struct2json -- C结构体与 JSON 快速互转库V1.0发布

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/zhutianlong/article/d ...

  4. MySQL之二进制日志

    一.Binlog日志格式 根据日志定义的格式不一样,可以分为Statement格式.Row格式或者MIXED格式 mysql5.6----> | binlog_format | STATEMEN ...

  5. ElasticSearch——原始文档和倒排索引

    一.原始文档 如上图所示, 第二象限是一份原始文档,有title和content2个字段,字段取值分别为”我是中国人”和” 热爱共X产党”,这一点没什么可解释的.我们把原始文档写入Elasticsea ...

  6. DB2中的NVL和NVL2函数

    NVL函数是一个空值转换函数 NVL(表达式1,表达式2) 如果表达式1为空值,NVL返回值为表达式2的值,否则返回表达式1的值. 该函数的目的是把一个空值(null)转换成一个实际的值.其表达式的值 ...

  7. iOS-AVFoundation生成缩略图

    使用MPMoviePlayerController来生成缩略图足够简单,但是如果仅仅是是为了生成缩略图而不进行视频播放的话,此刻使用 MPMoviePlayerController就有点大材小用了.其 ...

  8. SMOS数据产品介绍与下载方法

    1. SMOS数据介绍 The Soil Moisture and Ocean Salinity (SMOS) 卫星是欧空局发射的一颗以探测地球土壤水含量以及海表盐度为目标的卫星,卫星所搭载的唯一载荷 ...

  9. 【miscellaneous】gstreamer构建的简单方法

    在博文"Gstreamer在Ubuntu上的安装和MP3的播放"中,写了在ubuntu上从头到尾构建gstreamer的详细过程,那是我在一次小项目培训中和队友一起努力了将近一周的 ...

  10. opencv 直方图

    1.简介 对输入图像进行直方图均衡化处理,提升后续对象检测的准确率在OpenCV人脸检测的代码演示中已经很常见.此外对医学影像图像与卫星遥感图像也经常通过直方图均衡化来提升图像质量. 图像直方图均衡化 ...