首页 > 其他分享 >数位dp学习笔记

数位dp学习笔记

时间:2023-09-29 14:55:07浏览次数:35  
标签:题型 multi 笔记 bool 例题 dp 数位

数位dp学习笔记

目录

数位dp

定义:

...好像就是对数位进行dp,统计方案数。

题型特征:

通常会有10组左右的询问,每一次询问你较大(1e18左右)的区间内满足某个条件的数的数量。

dp设计:

dp一般会有2到4维。

  1. 通常情况下,第一维i表示现在这个n位数把最大的i位确定了。
  2. 第二位用于存放受限限制的某种信息。例如要是题要求你找有关gcd的东西,就开一维来存储这个信息。
  3. 第三位是个bool数(当然用记忆化搜索的话就可以不用开这一维,但也要记录)用于记录当前是否达到了最大值。
    这里解释一下为甚要开第三维,比如要求你找的区间是1到114514,但是你在第一位就不能够填9这么大的数字。但是呢,要是没满足这个条件的话,例如我第三位填的3,我后面就可以填9了。
  4. 第四位是bool数,视情况而定要不要加入,主要是为了判断前导零的影响,例如114514我第一位填0是可以的,但是会不会影响到受限制的那个信息呢?有可能呢,所以就相当于一种小型分类讨论吧。
  5. 当然你还可以开更多的维度,作用同“2”

dp转移

dp常利用记忆化搜索老解决。建议看着以下例题及代码注释进行理解。

例题:BZOJ 3679

这一道题很明显符合特征,我把我的代码呈现一下。

ll dfs(int pos, ll multi, bool head, bool limit)    //limit的时候,要判断是否填数字刚好在上限,head的时候,我们需要考虑到前导零
{
    if(multi > N) return 0;//超过限定范围,没必要继续下去了(肯定不会贡献)
    if(mp[multi] == 0) mp[multi] = ++cnt;//(special)因为数字之积的值域较大,但是真正能乘出来组成的数字较少,利用map来离散化,这个不是模板部分,这是这道题的一个特殊点
    if(pos <= 0) return multi > 0 && multi <= N;//进行统计,因为这道题的满足条件就是这个,所以直接判断就好。有的题还要专门写个函数来搞他。
    if(head && !limit && dp[pos][mp[multi]] != -1) return dp[pos][mp[multi]];//记忆化搜索,记得前两个条件也要加上
    ll ans = 0;
    int num = limit?digit[pos]:9;//填的数字在上限时,最多只能填到区间的上限的这一位的值,否则的话0-9随便取
    for(int i=0; i<=num; i++)
    {
        if(i == 0)//这下面都是小型的分类讨论,主要是在后面两个bool数的决定上。
        {
            if(head) ans += dfs(pos - 1, multi * i, true, limit && i == num);
            else ans += dfs(pos - 1, 0, false, limit && i == num);
        }
        else
        {
            if(head) ans += dfs(pos - 1, multi * i, true, limit && i == num);
            else ans += dfs(pos - 1, i, true, limit && i == num);
        }
    }
    if(!limit && head) dp[pos][mp[multi]] = ans;//记忆化,记得前两个条件
    return ans;
}
ll solve(ll x)//这里的x是上届的这个数
{
    int pos = 0;
    while(x)//找到上届的这个数的每一位具体是什么,用于对第一个bool数进行满足
    {
        digit[++pos] = x%10;
        x /= 10;
    }
    return dfs(pos, 0, false, true);
}

其他的题型除了第二维会有大幅度变化外没有大多区别,这边建议不会设计状态的话就看看题解。
因为第二维有可能设计状态压缩什么的,这又是另一个范畴了。

标签:题型,multi,笔记,bool,例题,dp,数位
From: https://www.cnblogs.com/linghusama/p/17737000.html

相关文章

  • 《程序员修炼之道:从小工到专家》第一第二章读书笔记
    第一章:追求实效的哲学第一节:我的源码被猫吃了在开发过程中,我们经常会遇到一些意想不到的技术问题,导致交付延迟等情况。然而,作为程序员,我们需要诚实和坦率地面对这些问题,并勇于承认自己的错误。我们应该以专业的态度处理这些问题,而不是找借口。此外,我们要对自己承担的责任负责。......
  • 国庆NOIP储备营讲课笔记
    Day1(基础算法)讲师:余快枚举法例题1给定一个数\(x\),判断\(x\)是不是质数。朴素算法:枚举\([2,x−1]\)之间所有的整数\(i\),逐个判断\(x\)是否被\(i\)整除,若都不能整除则\(x\)是质数,时间复杂度\(O(x)\),搞个\(10^9\)直接卡过。该怎么优化呢?优化枚举范围:只需枚举到......
  • 学习笔记
    周屹梁的学习笔记个人各平台地址博客地址:https://www.cnblogs.com/zylyehuo/gitee地址:https://gitee.com/zylyehuogithub地址:https://github.com/zylyehuo夯实基础四元数法|代价地图组成(多层叠加)|通过openpyxl操作excel表格|Ubuntu下查看ip|Windows终......
  • [笔记]操作系统_2024年考纲
    一、操作系统基础(一)操作系统的基本概念(二)操作系统发展历程(三)程序运行环境1.CPU运行模式内核模式,用户模式。2.中断和异常的处理3.系统调用4.程序的链接与装入5.程序运行时的内存映像与地址空间(四)操作系统结构分层,模块化,宏内核,微内核,外核。(五)操作系统引导(六)虚拟......
  • 9.29 《代码大全2》阅读笔记
    《代码大全2》是一本非常经典的软件开发书籍。在书中,强调了比较优秀的代码结构和命名规范的重要性。书中注释的部分帮助我理解怎么去编写有意义的注释,合适的注释可以提供代码理解上的便利,但是过多或者无关的注释会干扰代码的可读性。还有书中关于代码复用和模块化的内容帮助学习......
  • 初中生都能看懂的 LCT 学习笔记
    初中生都能看懂的LCT学习笔记这篇文章偏向入门,旨在尽可能解决一类问题——动态树,主要讲述并且整理LCT算法及其一些变式。目前其变式例题作者还在整理之中,编者保证会把变式例题持续更新。0.前置知识splay。我可以猜测一下,你们可能看到splay,然后就可能去学了splay树,然......
  • Python笔记:基本数据结构(容器)的优化
    列表的性能问题队列的弹出问题利用Python的原生语法很难写出一个真正完全能达到\(O(1)\)的队列,究其原因是由于insert方法的时间复杂度问题:classqueue: def__init__(self,q): self.q=[] defpopright(self): self.q.pop() defappendleft(self,elem): self.q.ins......
  • 信息安全系统设计与实现学习笔记4
    学习笔记4-总结知识点总结1.文件操作级别硬件级别:mkfs:格式化磁盘分区,为系统做好准备。fsck:检查和维修系统。碎片整理:压缩文件系统中的文件。操作系统内核中的文件系统函数:提供基本文件操作支持,例如:kmkdir(),krmdir()kchair(),kgetCwd()klink(),kunlink(......
  • 权值线段树 学习笔记
    8月集训学了权值线段树,当时没怎么加强训练。国庆刚好开始有时间,巩固巩固。补上学习笔记。首先介绍权值树。其本质是一个记录每个数出现次数的线段树,也就是由桶建成的树。接下来介绍各种操作。1.插入。由于统计的是出现次数,从这个数往上依次加1即可。voidinsert(intx,int......
  • 矩阵学习笔记
    矩阵是一种数学概念,在\(OI\)中有着重要应用。一个矩阵有行,列,以及里面的数字。如图便是一个\(2\)行\(3\)列的矩阵:\[\begin{bmatrix}1&2&3\\4&5&6\\\end{bmatrix}\]矩阵数乘:\(\lambdaA\)就是将\(\lambda\)依次乘进每个矩阵。矩阵乘法:\(A\timesB=C\),那么\(C_{......