老子听懂了!!!!!

好感动!!!

不说多了:Keywords: 数位DP,二进制,异或。

“在信息学竞赛中,有一类与数位有关的区间统计问题。这类问题往往具有比较浓厚的数学味道,无法暴力求解,需要在数位上进行递推等操作。”——刘聪《浅谈数位类统计问题》

这类问题往往需要一些预处理,这就用到了数位DP

例题:不要62

需要统计区间[l,r]的满足题意的数的个数,这往往可以转换成求[0,r]-[0,l)

基本思想与方法

有了上述性质,我们就可以从高到低枚举第一次<n对应位是哪一位。

这样之前的位确定了,之后的位就不受n的限制即从00...0~99...9,可以先预处理,然后这时就可以直接统计答案。

预处理F数组。

F[i,st] 代表 位数为i(可能允许前导0。如00058也是个5位数),状态为st的方案数。这里st根据题目需要确定。

如i=4,f[i,st]也就是0000~9999的符合条件的数的个数(十进制)

决策第i位是多少(such as 0~9)

F[i,st] = F[i,st] + f[i–1,st']

st'为相对应的状态

参照刚刚所说的基本思路。预处理f数组,然后统计[0,m] - [0,n).

f[i,j]代表开头是j的i位数中不含"62"或"4"的数有几个。

如f[2,6]包含60,61,63,65,66,67,68,69

  1. for(i=;i<=;i++)//因为数据为1000000,所以预处理7位
  2. for(j=;j<=;j++)//第i位
  3. for(k=;k<=;k++)//第i-1位
  4. if(j!=&&!(j==&&k==))f[i][j]+=f[i-][k];

接下来,怎么算出0-n和0-m区间的答案数呢?

用一个通用函数(Cal):

  1. 456=f[][]+f[][]+f[][]+f[][]+f[][]//(为什么不枚举到5呢?因为再下一位枚举了)
  2.  
  3. +f[][]+f[][]+f[][]+f[][]+f[][]//(就是这一位)
  4.  
  5. +f[][]+f[][]+f[][]+f[][]+f[][]+f[][]+f[][].
    具体代码如下:
  1. #include<cstdio>//最右边是第一位
  2. #include<cstring>
  3. #include<cmath>
  4. #include<cstdlib>
  5. #include<iostream>
  6. #include<algorithm>
  7. using namespace std;
  8. int f[][];
  9. int Cal(int k)//求1~k中有多少符合的数.
  10. {
  11. int len,digit[],i,j,ans=;
  12. memset(digit,,sizeof(digit)),len=;//digit[i]为当前的某个数从右到左第i个位置的数是多少.
  13. while(k>){digit[++len]=k%;k/=;}
  14. for(i=len;i>=;i--)
  15. {
  16. for(j=;j<=digit[i]-;j++)//每一位只能到k的下一位,所以计算的数实际只能到k-1.所以Cal()中传数要加1.
  17. {
  18. if(j!=&&!(j==&&digit[i+]==))ans+=f[i][j];
  19. }
  20. if(digit[i]==||(digit[i]==&&digit[i+]==))break; //如果这一位本来就没法,则后面的情况报废
  21. }
  22. return ans;
  23. }
  24. int main()
  25. {
  26. int n,m,i,j,k;
  27. memset(f,,sizeof(f));//f[i][j]为以j开始的且不含"62"和"4"位数为i的个数.
  28. f[][]=;
  29. for(i=;i<=;i++)
  30. {
  31. for(j=;j<=;j++)//第i位
  32. {
  33. for(k=;k<=;k++)//第i-1位
  34. {
  35. if(j!=&&!(j==&&k==))f[i][j]+=f[i-][k];
  36. }
  37. }
  38. }
  39. while()
  40. {
  41. scanf("%d %d",&n,&m);
  42. if(n==&&m==)break;
  43. printf("%d\n",Cal(m+)-Cal(n));//因为当前的Cal(k)是计算出从1到k-1的符合条件的数的个数,所以要计算n~m的个数要用Cal(m+1)-Cal(n).
  44. }
  45. return ;
  46. }

变式模板题_P2657 [SCOI2009]windy数

这题还是很简单的啦(差点没做出来

个位打表大佬请离开(包括记搜),我这里讲的是DP!!!

首先Cal(b+1)-Cal(a),大家都懂吧(算了,复制一遍吧<<((因为当前的Cal(k)是计算出从1到k-1的符合条件的数的个数,所以要计算a~b的个数要用Cal(b+1)-Cal(a).))>>)

f[i][j]定义一样,以j开始的且符合条件的总位数为i的答案个数.(好绕啊)

预处理转移不用讲吧:f[i][j]+=f[i-1][k];(还是复制了)

有个小细节,每个一位数答案都为1,所以分f[1][j]=0.

重点讲讲不同之处(Cal函数):

显然位数比x要小的数字都是合法的都在[1,x)区间内,直接统计就行.(第一次加ans)

位数和x一样最高位的数字比x小的数字都是合法的都在[1,x)区间内直接统计就行(第二次加ans)

位数和x一样,最高位又和x一样我们从左到右扫一遍x各个位子上的数字大小然后枚举合法的该位子上的数[0,9]判断是否合法就行。(第三次加ans)

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int f[][];
  4. int a,b;
  5. int digit[],cnt,ans;
  6. void init ()
  7. {
  8. for (int i=;i<=;i++) f[][i]=;
  9. for (int i=;i<=;i++)
  10. for (int j=;j<=;j++)
  11. for (int k=;k<=;k++)
  12. if(abs(j-k)>=)
  13. f[i][j]+=f[i-][k];
  14. }
  15. int Cal(int x)
  16. {
  17. //freopen("a.in", "r", stdin);
  18. memset(digit,,sizeof(digit));
  19. ans=;
  20. cnt=;
  21. while(x)
  22. {
  23. digit[++cnt]=x%;
  24. x/=;
  25. }
  26. //三种情况
  27. for (int i=;i<cnt;i++)
  28. for (int j=;j<=;j++)
  29. ans+=f[i][j]; //在不到x位数前,所有情况符合。
  30. for (int i=;i<digit[cnt];i++) ans+=f[cnt][i]; //x位数,最高位未到digit[cnt]。
  31. for (int i=cnt-;i>=;i--)//x位数,最高位到digit[cnt]
  32. {
  33. for (int j=;j<digit[i];j++)
  34. if(abs(j-digit[i+])>=)
  35. ans+=f[i][j];
  36. if(abs(digit[i]-digit[i+])<)
  37. break;
  38. }
  39. //printf("%d\n",ans);
  40. return ans;
  41. }
  42. void work()
  43. {
  44. cin>>a>>b;
  45. cout<<Cal(b+)-Cal(a)<<'\n';
  46. }
  47. int main()
  48. {
  49. init();
  50. work();
  51. return ;
  52. }

练习:P2602 [ZJOI2010]数字计数

同步题解

加油……

浅说——数位DP的更多相关文章

  1. 【BZOJ1662】[Usaco2006 Nov]Round Numbers 圆环数 数位DP

    [BZOJ1662][Usaco2006 Nov]Round Numbers 圆环数 Description 正如你所知,奶牛们没有手指以至于不能玩"石头剪刀布"来任意地决定例如谁 ...

  2. bzoj1026数位dp

    基础的数位dp 但是ce了一发,(abs难道不是cmath里的吗?改成bits/stdc++.h就过了) #include <bits/stdc++.h> using namespace ...

  3. uva12063数位dp

    辣鸡军训毁我青春!!! 因为在军训,导致很长时间都只能看书yy题目,而不能溜到机房鏼题 于是在猫大的帮助下我发现这道习题是数位dp 然后想起之前讲dp的时候一直在补作业所以没怎么写,然后就试了试 果然 ...

  4. HDU2089 不要62[数位DP]

    不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  5. 数位DP GYM 100827 E Hill Number

    题目链接 题意:判断小于n的数字中,数位从高到低成上升再下降的趋势的数字的个数 分析:简单的数位DP,保存前一位的数字,注意临界点的处理,都是套路. #include <bits/stdc++. ...

  6. 数位dp总结

    由简单到稍微难点. 从网上搜了10到数位dp的题目,有几道还是很难想到的,前几道基本都是模板题,供入门用. 点开即可看题解. hdu3555 Bomb hdu3652 B-number hdu2089 ...

  7. 数位DP入门

    HDU 2089 不要62 DESC: 问l, r范围内的没有4和相邻62的数有多少个. #include <stdio.h> #include <string.h> #inc ...

  8. 数位DP之奥义

    恩是的没错数位DP的奥义就是一个简练的dfs模板 int dfs(int position, int condition, bool boundary) { ) return (condition ? ...

  9. 浅谈数位DP

    在了解数位dp之前,先来看一个问题: 例1.求a~b中不包含49的数的个数. 0 < a.b < 2*10^9 注意到n的数据范围非常大,暴力求解是不可能的,考虑dp,如果直接记录下数字, ...

随机推荐

  1. #748 – 获得按下时对应位置点的大小(Getting the Size of a Contact Point during Raw Touch)

    原文:#748 – 获得按下时对应位置点的大小(Getting the Size of a Contact Point during Raw Touch) 原文地址:https://wpf.2000t ...

  2. 通过浏览器调用Android要么iOS应用

    在做移动应用的单点登录时间,需要点击浏览器中启动链接APP和参数传递APP其中,用于处理相应的接口,现在,通过浏览器调用Android和iOS在应用过程中实现理清固化博客.为了查询. 一:通过浏览器调 ...

  3. WPF: FishEyePanel/FanPanel - 自定义Panel

    原文:WPF: FishEyePanel/FanPanel - 自定义Panel 原文来自CodeProject,主要介绍如何创建自定义的Panel,如同Grid和StackPanel. 1) Int ...

  4. [视频]mac系统下虚拟机parallels安装ubuntu 14.04视频教程

    此文是http://www.mr-wu.cn/install-ubuntu-14-04-on-parallels-for-mac/这篇博文的补充,为整个ubuntu 14.04安装过程的视频录像. m ...

  5. spring boot 配置swagger UI

    springboot集成swaggerUI 有这样的需求 1.在每个接口上都增加一个字段: 2.接口文档只展示满足一定条件URL的接口 配置文件 详细看代码 import org.springfram ...

  6. 专访Jeffrey Richter:Windows 8是微软的重中之重

    Jeffrey Richter 以其多本 Windows 核心技术的经典著作而闻名,同时,他深入掌握微软的 .NET 等一系列核心技术,他所创办的 Wintellect 公司与微软有密切的合作关系,他 ...

  7. Win8 Metro(C#)数字图像处理--2.62图像对数增强

    原文:Win8 Metro(C#)数字图像处理--2.62图像对数增强  [函数名称]   对数增强      WriteableBitmap LogenhanceProcess(Writeabl ...

  8. Win8Metro(C#)数字图像处理--2.27图像加法运算

    原文:Win8Metro(C#)数字图像处理--2.27图像加法运算  [函数名称] 图像加法函数AddProcess(WriteableBitmap src, WriteableBitmap a ...

  9. Python标准库(3.x): 内建函数扫盲

    Built-in Functions abs() dict() help() min() setattr() all() dir() hex() next() slice() any() divmod ...

  10. C# Lambda表达式Contains方法 like

    原文:Lambda表达式Contains方法 like 1.使用Contains方法的必备条件: Contains等价于SQL中的like语句.不过Contains只针对于字符串(string)类型的 ...