http://www.lydsy.com/JudgeOnline/problem.php?id=1026

Description

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

Input

  包含两个整数,A B。

Output

  一个整数

Sample Input

【输入样例一】
1 10
【输入样例二】
25 50

Sample Output

【输出样例一】
9
【输出样例二】
20

————————————————————————————————————

今天开始学数位dp了!

所以趁着这道题还简单赶紧记录下来。

设dp(n)表示0~n的windy数个数。

设f[i][j][0/1]表示当前处理到第i位数为j,此时前i位数比n的前i位数小于等于(为0)/大于(为1)的数的个数。

显然我们求a~b的个数可以利用前缀和,只需要求dp(b)再减去dp(a-1)即可。

那么对于函数dp(n),其主要流程:

1.将n拆成十进制数,存在数组中(这里数组为a,长度为len)

2.特殊处理第一层:

  1. for(int i=;i<=;i++){
  2. if(i<=a[])f[][i][]=;
  3. else f[][i][]=;
  4. }

3.枚举i=2~len层并处理之,枚举当前层填充的数字j和上一层填充数字k。当符合windy数的条件时开始更新,更新方程较显然就不多说了:

  1. if(j<a[i])
  2. f[i][j][]+=f[i-][k][]+f[i-][k][];
  3. else if(j==a[i])
  4. f[i][j][]+=f[i-][k][],f[i][j][]+=f[i-][k][];
  5. else f[i][j][]+=f[i-][k][]+f[i-][k][];

4.得出答案。这里需要注意对于最后一层需要特殊处理防止越出0~n的范围。也很显然。

整套流程至此完毕,复杂度显然为log级别。

PS:判断是否为windy数很简单,这里用了一个辅助数组c[i][j]表示abs(i-j),借此判断能够美化代码(滑稽)

  1. #include<cstdio>
  2. #include<cstring>
  3. using namespace std;
  4. const int N=;
  5. int a[N],f[N][N][],c[N][N];
  6. int dp(int x){
  7. int len=;
  8. while(x)a[++len]=x%,x/=;
  9. if(len==)a[++len]=;
  10. memset(f,,sizeof(f));
  11. for(int i=;i<=;i++){
  12. if(i<=a[])f[][i][]=;
  13. else f[][i][]=;
  14. }
  15. for(int i=;i<=len;i++){
  16. for(int j=;j<=;j++){
  17. for(int k=;k<=;k++){
  18. if(c[j][k]>=){
  19. if(j<a[i])
  20. f[i][j][]+=f[i-][k][]+f[i-][k][];
  21. else if(j==a[i])
  22. f[i][j][]+=f[i-][k][],f[i][j][]+=f[i-][k][];
  23. else f[i][j][]+=f[i-][k][]+f[i-][k][];
  24. }
  25. }
  26. }
  27. }
  28. int ans=;
  29. for(int i=;i<=a[len];i++)ans+=f[len][i][];
  30. for(int i=len-;i;i--){
  31. for(int j=;j<=;j++){
  32. ans+=f[i][j][]+f[i][j][];
  33. }
  34. }
  35. return ans;
  36. }
  37. int main(){
  38. for(int i=;i<=;i++){
  39. for(int j=i;j<=;j++){
  40. c[i][j]=c[j][i]=j-i;
  41. }
  42. }
  43. int a,b;
  44. scanf("%d%d",&a,&b);
  45. printf("%d\n",dp(b)-dp(a-));
  46. return ;
  47. }

BZOJ1026:[SCOI2009]windy数——题解的更多相关文章

  1. BZOJ1026 SCOI2009 windy数 【数位DP】

    BZOJ1026 SCOI2009 windy数 Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B ...

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

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

  3. bzoj1026: [SCOI2009]windy数(传说你是数位DP)

    1026: [SCOI2009]windy数 题目:传送门 题解: 其实之前年少无知的时候好像A过...表示当时并不知道什么数位DP 今天回来深造一发... 其实如果对这个算法稍有了解...看到这题的 ...

  4. BZOJ1026: [SCOI2009]windy数[数位DP]

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

  5. 【数位DP】bzoj1026: [SCOI2009]windy数

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

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

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

  7. bzoj千题计划117:bzoj1026: [SCOI2009]windy数

    http://www.lydsy.com/JudgeOnline/problem.php?id=1026 数位DP 如果前一位填的是0, 0是前导0,下一位可以随便填 0不是前导0,下一位不能填1 为 ...

  8. C++ 洛谷 P2657 [SCOI2009]windy数 题解

    P2657 [SCOI2009]windy数 同步数位DP 这题还是很简单的啦(差点没做出来 个位打表大佬请离开(包括记搜),我这里讲的是DP!!! 首先Cal(b+1)-Cal(a),大家都懂吧(算 ...

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

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

随机推荐

  1. Hive支持行级update、delete时遇到的问题

    Hive从0.14版本开始支持事务和行级更新,但缺省是不支持的,需要一些附加的配置.要想支持行级insert.update.delete,需要配置Hive支持事务.(行级的insert好像不配置也能运 ...

  2. PLSQL集合类型

    PLSQL集合类型   --联合数组(索引表) /* 用于存储某个数据类型的数据集合类型 .通过索引获得联合数组中得值 如下例子: */ DECLARE CURSOR cur_chars IS SEL ...

  3. 「日常训练&知识学习」树的直径(POJ-1849,Two)

    题意 一个城市由节点和连接节点的街道组成,街道是双向的. 此刻大雪覆盖了这个城市,市长确定了一些街道要将它们清扫干净,这些街道保证所有的节点可以通过它们连通而且街道数目尽可能小. 现有两台相同的扫雪机 ...

  4. 「日常训练」 Longest Run on a Snowboard (UVA-10285)

    题意 其实就是一条二维的LIS,但是还是做的一愣一愣的,多努力. 考虑$dp[i][j]$为从(i,j)出发的二维LIS的最大值,那么$dp[i][j]=max\{dp[i−di[k]][j−dj[k ...

  5. Objective-C 点语法 成员变量的作用域 @property和@synthesize关键字 id类型

    点语法 1.利用点语法替换set方法和get方法 方法调用 Student *stu = [Student new]; [stu setAge : 18]; int age = [stu age]; ...

  6. Bootstrap栅格系统基本使用

    1.什么是栅格系统: 在Bootstrap中,它提供了一套响应式.移动设备优先的流式栅格系统,随着屏幕或视口(viewport)尺寸的增加,系统会自动分为最多12列.栅格系统用于通过一系列的行(row ...

  7. 利用nohup后台运行jar文件包程序

    Linux 运行jar包命令如下: 方式一: java -jar XXX.jar特点:当前ssh窗口被锁定,可按CTRL + C打断程序运行,或直接关闭窗口,程序退出 那如何让窗口不锁定? 方式二 j ...

  8. 【shell 练习4】编写Shell用户管理脚本(二)

    一.创建.删除.查看用户,随机生成八位数密码 #!/bin/bash #Author:yanglt #!/bin/bash #Author:yanglt #Blog:https://www.cnblo ...

  9. 最小生成树(II)与Kruskal算法

    为防止网页加载过慢,故分两章.上接https://www.cnblogs.com/Uninstalllingyi/p/10479470.html Kruskal算法——将森林合并成树 玩过瘟疫公司吗… ...

  10. 十二:NodeManager

    NM负责启动和管理节点上的containers.AM通过containers来运行任务. Health Checker Service 创建检查服务     NM运行一个检查服务来检查节点的状态,该服 ...