数位dp 笔记

数位dp一直是我的弱项,惦记好久了,最近补了补,感觉还行。

解决的问题 & 主体思想

解决一个区间中,满足某些条件(与每一位有关)的数的数量(或者带权的和)。

做法:考虑求前缀 \([1,x]\) 的答案。

如果你是新手,请先考虑一下大概要怎么做,再继续看

先把位(不一定是十进制)拆开来,然后是一个形如 "dp到第 \(i\) 位,..." 的 dp,一般可以用记忆化搜索,一位一位的填,使得它看起来友好一些(个人感觉这样可读性好)。

然后要解决 \(\le x\) 的限制。每次按照这样的规则来填数字:

  • 默认每一位都不能超过 \(x\) 对应的位
  • 如果有一位小于了 \(x\) 对应的位,则后面就没限制了

这个很好理解。比如说现在钦点下来是 \(123***\),\(x=123456\),那后面显然不能超过 \(456\)。

而如果现在钦点下来是 \(122***\),那它就算是 \(122999\),也不会超过 \(x\)。

用一个 lim 标记维护当前是否卡到上界。注意它应该被记在 dp 状态里。

入门 —— windy数

求区间满足:任意相邻两位的差都不超过 \(2\) 的数,的数量。

dp 状态:到第几位,当前选了什么(以决定下一个可不可以选),lim

然后每次 dfs 扩展的时候,判断一下下一个填的是否合法,再加个记忆化,就行了。

代码

绕一个弯 —— 萌数

求区间满足:将数看成字符串,没有任何长度 \(\ge 2\) 的回文串的数,的数量。

没有任何长度 \(\ge 2\) 回文串 \(\rightarrow\) 任意一个字符和它前面一个,两个都不同。

这样就保证了没有长度等于 \(2,3\) 的回文串,然后其余的回文串都是由这两种扩展出来的,自然也没有了。

剩下就很好 dp 了,和上一个差不多。

代码

the end? —— 恨7不成妻

hdu的题,我第一次学数位dp的时候被老师称作“毕业题”

你要能把这个题写出来,你数位dp就差不多了

当时看着老师标程打的,现在简单复习了一下,发现还挺好想的 然后把它秒了,其实就是一个傻逼缝合怪题

要满足三个条件:

  • 不能有数位7
  • 数位和不能是7的倍数
  • 数本身不能是7的倍数

区间求满足条件平方和。

这里涉及到一个带权求和。带权求和状态要变一下,表示从这位开始截取,的带权和。

比如说 \(x=123\),填好了 \(11*\),满足条件的数有 \(111\),\(113\),\(114\),\(116\),\(118\)

带权和为 \(1^2+3^2+4^2+6^2+8^2=126\)

为什么要做一步截取呢?因为要方便转移。考虑转移,相当于,我先确定好后面若干位,在它们的前面都填上相同的数字(这里相当于放上了 \(1\))

然后填相同的数字可以看做是加法 (这里相当于 \(+10\))

然后平方和,整体加,好做吧:再维护数量和一次方和,设为 dp[...][0/1/2],对应数量,和,平方和

设现在整体加的为 \(a\),后面一位的 dp[...][0/1/2] 记下来为 nex[0/1/2],现在的是 cur[0/1/2],则有:

cur[0]+=nex[0];
cur[1]+=nex[1]+nex[0]*a;
cur[2]+=nex[2]+2*nex[1]*a+nex[0]*a*a

(就是拆括号搞一下就行)

对于条件:

  • 每次不填 \(7\)
  • 记录数位和对 \(7\) 的余数,放在状态里,取 \(0\) 那个状态
  • 记录整个数对 \(7\) 的余数,放在状态里,取 \(0\) 那个状态

代码

小心细节 [SDOI2016]储能表

求 \(\sum\limits_{i=0}^{n-1} \sum\limits_{j=0}^{m-1} \max(i\oplus j-k,0)\)

\(n,m,k\le 10^{18}\)

后面等价成 \(>k\) 的和,减去 \(>k\) 的数量乘以 \(k\)

拆成二进制,做数位 \(dp\)。记下三个 lim,表示是否卡在 \(n\) 的上界,\(m\) 的上界,\(k\) 的下界 (因为 \(k\) 那边是个 \(>\) 的限制)

然后上一题类似的求一下带权和就行了,要维护一下数量和总和。

代码

复杂度起飞 [AHOI2009]同类分布

由于数位 dp 的基本模型只有一个 log,所以可以带很多别的

题意:求区间能整除数位和的数的数量

比如 \(12\) 就满足条件因为 \(1+2\) 是 \(12\) 的倍数

\(x\le 10^{18}\)

注意到数位和不会超过 \(9\times 18=162\)

先枚举数位和 \(k\),然后 dp 里设两维,一维表示当前数位和,一维表示当前数模 \(k\) 的余数。最后取答案就是 \(\%k=0\),数位和 \(=k\) 的那个状态

复杂度是 \((9\times \log n^3)\log n\),非常暴力

代码

数位dp 笔记的更多相关文章

  1. 数位DP笔记

    数位DP 1.定义: 数位dp是一种计数用的dp,一般就是要统计一个区间[L,R]内满足一些条件数的个数.所谓数位dp,字面意思就是在数位上进行dp: 数位的含义:一个数有个位.十位.百位.千位... ...

  2. 「笔记」数位DP

    目录 写在前面 引入 求解 特判优化 代码 例题 「ZJOI2010」数字计数 「AHOI2009」同类分布 套路题们 「SDOI2014」数数 写在最后 写在前面 19 年前听 zlq 讲课的时候学 ...

  3. 数位DP学习笔记

    数位DP学习笔记 什么是数位DP? 数位DP比较经典的题目是在数字Li和Ri之间求有多少个满足X性质的数,显然对于所有的题目都可以这样得到一些暴力的分数 我们称之为朴素算法: for(int i=l_ ...

  4. 算法笔记--数位dp

    算法笔记 这个博客写的不错:http://blog.csdn.net/wust_zzwh/article/details/52100392 数位dp的精髓是不同情况下sta变量的设置. 模板: ]; ...

  5. 数位DP复习笔记

    前言 复习笔记第五篇.(由于某些原因(见下),放到了第六篇后面更新)CSP-S RP++. luogu 的难度评级完全不对,所以换了顺序,换了别的题目.有点乱,见谅.要骂就骂洛谷吧,原因在T2处 由于 ...

  6. 【学习笔记&训练记录】数位DP

    数位DP,即对数位进行拆分,利用数位来转移的一种DP,一般采用记忆化搜索,或者是先预处理再进行转移 一个比较大略的思想就是可以对于给定的大数,进行按数位进行固定来转移记录答案 区间类型的,可以考虑前缀 ...

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

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

  8. 数位DP 学习笔记

    前言:鸣谢https://www.luogu.com.cn/blog/virus2017/shuweidp.感谢大佬orz ----------------------------- [引入] 首先要 ...

  9. [学习笔记] 数位DP的dfs写法

    跟着洛谷日报走,算法习题全都有! 嗯,没错,这次我也是看了洛谷日报的第84期才学会这种算法的,也感谢Mathison大佬,素不相识,却写了一长篇文章来帮助我学习这个算法. 算法思路: 感觉dfs版的数 ...

随机推荐

  1. Java将List中的实体按照某个字段进行分组的算法

    public void test() { List<User> list = new ArrayList<>(); //User 实体 测试用 String id,name; ...

  2. mysql字符串拼接

    逗号分隔拼接字符串 SELECT group_concat(USER_ID)from rocky_bankinfo         默认大小2014 2).可以简单一点,执行语句,可以设置作用范围   ...

  3. mysql免安装教程

    1. 下载MySQL Community Server 5.6.13 2. 解压MySQL压缩包    将以下载的MySQL压缩包解压到自定义目录下,我的解压目录是:    "D:\Prog ...

  4. [leetcode]669. Trim a Binary Search Tree寻找范围内的二叉搜索树

    根据BST的特点,如果小于L就判断右子树,如果大于R就判断左子树 递归地建立树 public TreeNode trimBST(TreeNode root, int L, int R) { if (r ...

  5. .NET Core学习笔记(8)——Entity Framework Core之Database First

    曾经我以为再也不会去弄啥Database First,然鹅我错了.这个世界上就是有啪啪打脸和真香的时候.当小伙伴拿着做好的DB表结构和SQL脚本递过来的时候,我知道我没法拒绝.望着他突起的肱二头肌和充 ...

  6. java普通io(stream)处理文件读写的过程

    场景:使用java的stream,从文件a读取内容,然后写进文件b,整个过程如下图所示(以linux系统为例) 步骤解析: 1.用户空间向内核空间发出指令--我要读取文件a 2.系统切换上下文,从用户 ...

  7. Java中几种常见的循环

    多重if_else: package com.dengchaoqun.ht; public class Double_For02 { /** * * 打印乘法表 */ public static vo ...

  8. ES6 class类 静态方法及类的继承

    一.class类 ES6之前都是定义函数以及函数的原型对象实现类型, 如果想要实现共享构造函数成员,可以用prototype来共享实现 ES6出现之后,使用class类的概念来实现原型的继承 二,静态 ...

  9. 数仓建设中最常用模型--Kimball维度建模详解

    数仓建模首推书籍<数据仓库工具箱:维度建模权威指南>,本篇文章参考此书而作.文章首发公众号:五分钟学大数据,公众号中发送"维度建模"即可获取此书籍第三版电子书 先来介绍 ...

  10. Both Dolby Atmos driver and API need to be installed问题的一个解决方法

    问题的原因在于缺少以下两个部分: Dolby Atmos driver:指你的声卡驱动中自带的杜比文件 如果驱动里没有,说明你的硬件可能不支持杜比,或者驱动太老没有包含杜比. Dolby Atmos ...