1. 问题描述:

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

输入格式

包含两个整数,A B。

输出格式

一个整数

输入输出样例

输入

1 10

输出

9

输入

25 50

输出

20

数据范围

100%的数据,满足 1 <= A <= B <= 2000000000

来源:https://www.acwing.com/activity/content/11/

2. 思路分析:

① 这道题目是一道经典的数位 dp 知识点的入门题目,与之前 acwing 中数字游戏的题目是类似的,只是题目中数字的位的限制条件不一样而已,但是整体的思路都是一样的。首先需要声明一个二维列表 f 用来已处理,其中 f[i][j] 的含义为当前有 i 位并且最高位为 j 的数目,我们可以使用一个init 方法递推得到 f 列表的值,使用 init 方法预处理的目的是为了能够直接计算出树中左边方案数目(将数字 x 的所有位看成是一棵树,分为左分支与右分支,左边分支考虑当前这一位填入 0~x-1,右边的分支填入 x 对于每一位都是这样处理,所以可以将其看成是一棵树),init 方法中得到列表 f 的值其实也是一个动态规划递推的过程,由小的位数递推到大的位数。然后使用一个 dp 方法计算出 [0,x] 区间中符合条件的数目,那么区间 [x,y] 中符合题目要求的数目为 f(y) - f(x - 1)。dp 方法中首先是将数组 x 的各位存储到一个列表 nums 中,从高位到低位开始遍历 nums 列表中的每一位,因为 windy 数是不包含前导 0 的(包含前导 0 会对后面的低位的数字造成影响),所以对于最高位我们是不可以填入 0 的,所以在遍历当前 nums 中的位的时候判断当前位是否是最高位,如果是最高位那么当前位置尝试的范围为 1~nums[i] - 1,否则为 0~nums[i] - 1,在循环中可以使用 i == len(nums) - 1 判断即可,如果成立那么从 1 开始否则从 0 开始,对于当前这一位尝试 0~nums[i - 1] 的数字,因为之前预处理过所以可以直接将 f 列表对应位置的值累加到结果中,并且声明一个 last 变量来记录前缀信息,对于这道题目 last=nums[i]。最后判断是否可以到达最右边的那个分支,如果可以那么 res++,其实举实际的例子会更容易理解一点。

② 因为 ① 中考虑的是不存在前导 0 的情况,最高位是从 1 开始的,实际上 windy 数有前导0的情况下是会影响最终的结果的,例如两位的 windy 数,如果存在前导 0 那么只有 02,03,04...09才是满足的,忽略掉了 01 这个数字,三位的 windy 数也会筛选掉一些结果,比如第二位只能是 2 之后的数字,所以把像 013...这样的 windy 数也筛选掉了,所以我们需要额外的情况。我们其实是就可以将最高位看成是0但是这个 0 被隐藏掉了所以总共的位数是少一位的,所以我们需要额外计算出总共有 1~len(nums) - 1位的数字,并且最高位为 1~9 的 windy 数,这样就可以忽略掉前导 0 的影响,这也是在遍历 nums 列表中的时候当前位为最高位的时候不能够直接考虑填 0 的原因,所以我们在最后可以枚举一下从 1~len(nums) - 1 范围的 f[i][j] 将其累加到结果中即可。在数位 dp 解决的过程中计算 [0,x] 中的数目都会计算前导 0 的情况,也即 01,02....001,002.....,这些前导 0 一般是没有什么影响的,但是对于这道题目来说是有影响的。

N = 11
f = [[0] * 10 for i in range(N)]# 初始化f列表, f[i][j]表示当前有i位数字且最高位为j的数目
def init():for i in range(10):f[1][i] = 1for i in range(2, N):for j in range(10):for k in range(10):if abs(j - k) >= 2:f[i][j] += f[i - 1][k]def dp(n: int):if n == 0: return 0nums = list()while n:nums.append(n % 10)n //= 10res = 0# 只要是比1~9的数字的绝对值大于等于2即可last = -2for i in range(len(nums) - 1, -1, -1):x = nums[i]# 如果当前是最高位那么应该从1开始否则从0开始for j in range(i == len(nums) - 1, x):if abs(j - last) >= 2:res += f[i + 1][j]if abs(x - last) >= 2:last = xelse:break# 最右边的那个分支if i == 0: res += 1# 可以看成是前导0隐藏掉的情况例如02 04 06...这些数字可以隐藏掉前导0那么也属于正确答案for i in range(1, len(nums)):for j in range(1, 10):res += f[i][j]return resif __name__ == '__main__':init()A, B = map(int, input().split())print(dp(B) - dp(A - 1))

windy数(数位dp)相关推荐

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

    大家觉得写还可以,可以点赞.收藏.关注一下吧! 也可以到我的个人博客参观一下,估计近几年都会一直更新!和我做个朋友吧!https://motongxue.cn 文章目录 P2657 [SCOI2009 ...

  2. bzoj 1026: [SCOI2009]windy数 数位DP算法笔记

    数位DP入门题之一 也是我所做的第一道数位DP题目 (其实很久以前就遇到过 感觉实现太难没写) 数位DP题目貌似多半是问从L到R内有多少个数满足某些限制条件 只要出题人不刻意去卡多一个$log$什么的 ...

  3. 【bzoj1026】[SCOI2009]windy数 数位dp

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

  4. BZOJ1026 [SCOI2009]windy数 数位dp

    欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1026 题目概括 求区间[A,B]中有多少数满足下面的条件. 条件:该数相邻两位之差不小于2. 题解 ...

  5. AcWing1083. Windy数(数位DP)题解

    题目传送门 题目描述 Windy 定义了一种 Windy 数:不含前导零且相邻两个数字之差至少为 2 的正整数被称为 Windy 数. Windy 想知道,在 A 和 B 之间,包括 A 和 B,总共 ...

  6. WINDY数----数位dp

    题目链接:https://ac.nowcoder.com/acm/problem/20268 题目描述 windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数 ...

  7. P2657 [SCOI2009]windy数(数位dp)

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

  8. 洛谷P2657 windy 数 数位dp

    题目背景 windy 定义了一种 windy 数. 题目描述 不含前导零且相邻两个数字之差至少为 2 的正整数被称为 windy 数.windy 想知道,在 a 和 b 之间,包括 a 和 b ,总共 ...

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

    题意 题目链接 Sol 很zz的数位dp $f[i][j]$表示第$i$位,前一位是$j$的方案数 转移的时候枚举一下是否相同即可 注意当lim达到上界的时候是不能记忆化的! /**/ #includ ...

  10. 题解 BZOJ1026 luogu P2657 [SCOI2009]windy数 数位DP

    BZOJ & luogu 看到某大佬AC,本蒟蒻也决定学习一下玄学的数位$dp$ (以上是今年3月写的话(叫我鸽神$qwq$)) 思路:数位$DP$ 提交:2次 题解:(见代码) #inclu ...

最新文章

  1. linux 下camera调试笔记【转】
  2. es5 温故而知新 创建私有成员、私有变量、特权变量的方法
  3. 转载--编写高质量代码:改善Java程序的151个建议(第5章:数组和集合___建议60~64)
  4. DDR线长匹配与时序
  5. DESUtils 加解密时 Given final block not properly padded bug小记
  6. JSON 之 SuperObject(11): TSuperTableString、TSuperAvlEntry
  7. 1622C. Set or Decrease
  8. asp.net 页面跳转的方法
  9. 54 搜索引擎及Lucene基础、elasticsearch使用基础、ES使用详解、ES查询及Logstash入门...
  10. 算法:动态规划,最大子数组之和 Maximum Subarray
  11. PHP语言基本数据类型
  12. Overleaf 硕士毕业论文参考文献格式设置
  13. errorC1083 无法打开源文件 c1xx
  14. c语言c11标准侯捷,C++新标准 C++11/14课件 (侯捷) 完整PDF
  15. tsx实现适配vue3的滚动列表插件
  16. java程序员必备英语词汇_java程序员常用英文单词整理
  17. ios版本与xcode版本
  18. OC循环渐进:文件管理--计算文件大小的五种方式
  19. 性能测试报告包括哪些内容?模板范文哪里找?看这里
  20. django-simple-captcha的使用

热门文章

  1. deepin系统维护(系统扩容)deepin live
  2. PS图片批量自动排版
  3. 信创办公–基于WPS的PPT最佳实践系列 (将幻灯片组织成节的形式)
  4. 面试——游戏测试工程师(20190918)
  5. 前端传图片file给后端,后端接收为空,0kb
  6. Java毕业设计-流浪动物救助系统
  7. 推荐一部励志电视剧《山海情》
  8. 编写你的应用程序(三)、3D图形
  9. Gluster升级遇到的问题
  10. 在MacOS上构建以太坊开发环境