首页 > 其他分享 >数位 DP - 知识点梳理

数位 DP - 知识点梳理

时间:2023-07-22 10:14:21浏览次数:53  
标签:知识点 int top long id DP 数位

本质上是一种基于数位的线性 DP。
通常用于区间统计问题。当暴力枚举会超时,数位 DP 可以对区间的值进行按位求解,有时使用位值原理,把每位上相同的数一起求解,降低时间复杂度,有时会用到高位优先的贪心思想。

实现

Luogu P4124 [CQOI2016] 手机号码
这就是一个区间统计问题。如果暴力枚举肯定会超时,现在考虑优化。
暴力枚举时,我们在判断下一位可能的值时,会检测已经确定的位是否出现了 \(4\) 或 \(8\),前面有没有连续 \(3\) 个的数字,还需要多少个数字才可能与当前数字组成连续 \(3\) 个的。当然还有一个不要忘记:已确定的位是否达到了上限。到这你可能有思路了:其实只要这些条件完全相同,我们并不关心前缀具体是什么。也就是说,我们可以把数位拆开,以数位位置以及上方一系列信息作为维度,进行线性 DP,这样就能避免很多重复的访问。
开始设计状态:首先我们需要记录已确定了多少位,然后是否出现了 \(4\) 或 \(8\),前面有没有连续的 \(3\) 个数字,当前正在连续的是什么数字,当前的连续长度,当前的前缀是否已经达到上限。我们发现,高位的状态依赖于低位的状态,因此从低位往高位一次更新即可。
上代码! (这里有个小提示:像这种状态顺序容易搞混的题推荐写成记忆化搜索)

#include<bits/stdc++.h>
using namespace std;

long long f[12][2][2][11][12][2][2];
bool have[12][2][2][11][12][2][2];
long long dfs (int rtb[], int id, int top, int cmbed, int cmbid, int cmblen, int have4, int have8) {
	if (id == 12) return cmbed;
	if (have[id][top][cmbed][cmbid][cmblen][have4][have8]) {
		long long ans = f[id][top][cmbed][cmbid][cmblen][have4][have8];
		return ans;
	}
	int tdg = top ? rtb[id] : 9;
	long long ans = 0;
	for (int i = 0;i <= tdg;i++) {
		if (id == 1 && i == 0) continue;
		if (i == 4 && have8) continue;
		if (i == 8 && have4) continue;
		int pcmbed = cmbed, pcmbid = cmbid, pcmblen = cmblen;
		if (cmbid == i) {
			pcmblen++;
			if (pcmblen >= 3) pcmbed = true;
		}
		else {
			pcmbid = i;
			pcmblen = 1;
		}
		ans += dfs (rtb, id + 1, top && (i == tdg), pcmbed, pcmbid, pcmblen, have4 || (i == 4), have8 || (i == 8));
	}
	have[id][top][cmbed][cmbid][cmblen][have4][have8] = true;
	return f[id][top][cmbed][cmbid][cmblen][have4][have8] = ans; 
}
int main () {
	int l[15], r[15];
	long long lt, rt;
	cin >> lt >> rt;
	lt--;
	int p = 11;
	while (lt) {
		l[p--] = lt % 10;
		lt /= 10;
	}
	p = 11;
	while (rt) {
		r[p--] = rt % 10;
		rt /= 10;
	}
	long long ansr = dfs(r, 1, 1, 0, 10, 0, 0, 0);
	memset(have, 0, sizeof(have));
	long long ansl = dfs(l, 1, 1, 0, 10, 0, 0, 0);
	cout << ansr - ansl << endl;
	return 0;
}

可以看到,数位 DP 利用的是数字处理时前缀不影响后面的情况的性质,只有这样按位设置维度并设置状态才不会有后效性。

拓展应用

数位 DP 的用处仅限于数位 DP 本身,因此不做拓展,但数位 DP 本身却有很多奇妙的方法。这里提供一些常用的数位处理方法。

问题 应对方法
整个数要整除一个数 状态上记录除法的余数,每过一位乘以 \(10\)
所得数要满足条件且字典序最大/小 不要暴力整,学会二分
整个数太大,不能每位枚举 利用暴力数据结构,如分块

同时,数位 DP 作为一种线性 DP,有时可以结合处理字符串的一些方法。
这是一道例题:Luogu P2481 [SDOI2010] 代码拍卖会
我们要求一个长度为 \(n\) 的单调不减序列,且整个序列的位值和能被 \(p\) 整除。
考虑求这个序列的差分序列。差分序列中都为正数,且和都不超过 \(9\)。
然后尝试满足被 \(p\) 整除的条件。利用位值原理,差分序列中每个数对于整个数的模数贡献是该数乘以它会影响到的数的位值和,直接求解即可。
这样这个问题就被转化成了背包问题,枚举每个 \(1\) 放的位置,使用数位 DP 进行优化。(所以为什么要把数位 DP 单独作为一个算法?)

总结

数位 DP 是一种特殊的基于字符串的线性 DP,处理时可以使用处理字符串的一些方法,和线性 DP 的一些方法,说明它会和其他 DP 类优化进行搭配。数位 DP 通常用于解决区间统计类问题。

标签:知识点,int,top,long,id,DP,数位
From: https://www.cnblogs.com/mindeveloped/p/numbers-dp.html

相关文章

  • 状态压缩 DP - 知识点梳理
    状态压缩DP,或状压DP,是对状态的一种优化。相比于普通DP,通过将高维状态压缩成一个数,减少了维度,并使维度更易于存储与维护。同时这样与bitset一样利用了计算机在\(O(1)\)内处理位运算的能力,大幅度优化了时间复杂度。一般当题目中的状态由多个\(0\)/\(1\)组成,数量不一定,且......
  • m基于扩频解扩+LDPC编译码的通信链路matlab误码率仿真,调制对比QPSK,16QAM,64QAM,扩频
    1.算法仿真效果matlab2022a仿真结果如下:     2.算法涉及理论知识概要      在现代通信系统中,扩频技术被广泛应用于数字通信链路中。扩频技术通过将要传输的信息序列与一个宽带的伪随机码序列进行卷积,将原始信号转换成一个具有更大带宽的扩频信号。在接收端......
  • K8S初始化报错:CRI v1 runtime API is not implemented for endpoint \"unix:///var/r
    报错具体内容:[preflight]Somefatalerrorsoccurred:[ERRORCRI]:containerruntimeisnotrunning:output:time="2023-07-21T09:20:07Z"level=fatalmsg="validateserviceconnection:CRIv1runtimeAPIisnotimplementedforendpoint\"un......
  • Hibernate初始化时在OneToOneSecondPass类中出现NullPointerException
    启动项目 Hibernate随即报错Causedby:java.lang.NullPointerException   atorg.hibernate.cfg.OneToOneSecondPass.doSecondPass(OneToOneSecondPass.java:135)  原因: 主类方,无外键方@OneToOne(mappedBy="carveEReviewproject",targetEntity=CarveEReviewcomment.cla......
  • 多个 Lector621 组网读取 PCB 板上的 DPM 码
    第一部分:现场需求/问题描述 客户购买了5套SICKLector621: 1. 客户要求视野范围500mm; 2. 安装高度:200mm以下; 3. DPM码:4mm*4mm(点数:16*16),分辨率0.25;第二部分:现场工作内容 1.产品功能和参数设置: a. 安装和电气连接:  安装图 1.单台读码器安装......
  • Scrapy 部署错误:subprocess.CalledProcessError 以及解决方案
    最近在使用Scrapy和Scrapyd时,我遇到了一个关于subprocess.CalledProcessError的问题。在这篇博文中,我将描述这个错误、找出的原因以及最后的解决方案。错误描述在使用scrapyd-deploy命令部署我的Scrapy项目时,我遇到了如下的错误:subprocess.CalledProcessError:Comma......
  • 【网络流,dp】Gym102220A Apple Business
    ProblemLink有一棵\(n\)个点的完全二叉树(点\(i\)的父亲是\(\lfloori/2\rfloor\)),第\(i\)个点有\(a_i\)个苹果。现在有\(m\)个订单,每个订单只接受\(u_i\)到\(v_i\)路径上的苹果,保证\(u_i\)是\(v_i\)的父亲,并且最多只接受\(c_i\)个苹果,单价为\(w_i\)。你可......
  • pdf自动化框架基础指南十三大类知识点
    少说话,直接上图,先给大家看一个大概的本自动化框架基础指,面向零基础、有一定自动化测试经验但缺乏系统的基础知识的人员目的是提供一个相对系统的自动化框架知识经验的分享,本文档不保证其先进性,精确性,欢迎拍砖打我下一步计划是准备耗费2-3个月业余时间,对IEEE中关键字驱动框架相关文......
  • 网络编程 p5 UDP编程
    UDP网络通信编程基本介绍类DatagramSocket和DatagramPacket实现了基于UDP协议网络程序。UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。DatagramPacket对象封装了UDP数据报,在数据报中包含了发......
  • 20230719-动态规划DP
    20230719数位DPP4127[AHOI2009]同类分布题目描述传送门求出[a,b]中各位数字之和能整除原数的数的个数\(a,b≤1e18\)Solution对于这种求是否能整除的题我们只有在最后才能得到答案这道题很明显是数位DP考虑用记忆化搜索来实现对于每一位我们需要维护前面的数字之......