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

数位DP 学习笔记

时间:2024-03-06 17:12:49浏览次数:26  
标签:lead int 笔记 枚举 limit len DP 数位

什么是数位DP

数位dp是与数字相关的一类计数问题。这这类问题中,一般给定一些限制条件,求满足第 \(K\) 小的数是多少,或者求区间 \([L,R]\) 内有多少个满足条件的数。

本文主要讲述如何解决 求区间 \([L,R]\) 内有多少个满足条件的数 这一类问题。

为什么要用数位dp

对于上述问题,如果只使用简单的暴力,时间复杂度为 \(O(n+?)\) 枚举的时间复杂度 + 验证的时间复杂度。

如果采用 \(dfs\) 枚举每一位的方法。则可以通过题目已有条件,进行一部分的剪枝。代码如下

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

const int N = 20;

int num[N];

int dfs(int len, bool limit, bool lead, /*一些参数记录是否符合条件*/) {
	//limit表示当前的最高数是否有限制 lead表示前导0 
	if(len == 0) return sum;
	int ans = 0;
	int maxx = limit ? num[len]:9; 
	for (int i = 0; i <= maxx; i++) {
		ans += dfs(len-1, limit&&(i==maxx), lead||i, /*一些参数*/);
	}
	return ans;
}

int work(int x, int i) {
	int len = 0;
	while (x) {
		num[++len] = x%10;
		x /= 10;
	}
	memset(f, -1, sizeof(f));
	return dfs(len, 1, 0, i, 0);
}
int main() {
	int a, b;
	scanf("%d %d", &a, &b);
	for (int i = 0; i <= 9; i++) {
		printf("%d ", work(b, i) - work(a-1, i));
	}
	return 0;
}

详解 \(limit\) 和 \(lead\)

\(limit\) 记录当前枚举到当前数位,是否有最高位限制。对于每个数位的最大数不一定为 \(9\) 。举个荔枝 对于区间 \([5,114514]\) ,我们枚举到 \(1?????\) 显然当前数位枚举的最大数不应该为 \(9\) ,要不然我们枚举出的数就会超过区间限制。

\(lead\) 记录当前数位的前一位是否为前导 \(0\) , 这一项的记录有时候并不是必要的。你需要根据题目来设计你的状态。

可这样时间复杂度仍旧不尽人意。

怎么用数位dp

我们观察到,有很多等价的状态被重复遍历。举个例子 \(114???\) ,和 \(124???\) 两个状态(在他们没有最大数限制的情况下),枚举接下来数位数字的状态树一定是相同的。那还有必要在重复枚举两个相同的子树吗?答案是显然的。所以我们可以通过记忆化来避免多次遍历相同的 \(dfs\) 子树。
代码如下

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

const int N = 15;

int a, b;
int num[N],f[N][N];

int dfs(int len, bool limit, bool lead, /*一些参数记录是否符合条件*/) {
	if(len == 0) {
		if(!lead) return 0;
		return 1;
	}
	if(!limit&& /*根据题目自定参数*/) return f[][];
	
	int ans = 0;
	int maxx = limit ? num[len]:9;
	for (int i = 0; i <= maxx; i++) {
		ans += dfs(len-1, limit&&(maxx==i), lead||i, /*一些参数记录是否符合条件*/);
	}
	if(!limit&&lead) f[len][last] = ans;
	return ans;
}

int solve(int x) {
	memset(f, -1, sizeof(f));
	int len = 0;
	while (x) {
		num[++len] = x%10;
		x /= 10;
	}
	if(len==0) return 0;
	return dfs(len, 1, 0, -2);
}
int main() {
	scanf("%d %d", &a, &b);
	printf("%d", solve(b)-solve(a-1));
	return 0;
}

参考资料

标签:lead,int,笔记,枚举,limit,len,DP,数位
From: https://www.cnblogs.com/wh1sky/p/18057033

相关文章

  • 音频功率放大器方案LM4863替代DP4863
    音频放大器是在产生声音的输出元件上重建输入的音频信号的设备,其重建的信号音量和功率级都要理想——如实、有效且失真低。音频范围为约20Hz~20000Hz,因此放大器在此范围内必须有良好的频率响应。根据应用的不同,功率大小差异很大,从耳机的毫瓦级到TV或PC音频的数瓦,再到“迷你”家庭立......
  • SimGRACE论文阅读笔记
    Abstract​ 图对比学习(GCL)已经成为图表示学习的一种主导技术,它最大限度地提高了共享相同语义的成对图增强之间的互信息。不幸的是,由于图数据的多样性,在扩充过程中很难很好地保存语义。目前,GCL的数据扩充大致可分为三种不令人满意的方式。第一,可以通过试错法手动选择每个数据集的......
  • pandas笔记(一)-- 大的国家(逻辑索引、切片)
    题目描述如果一个国家满足下述两个条件之一,则认为该国是大国:面积至少为300万平方公里人口至少为2500万编写解决方案找出大国的国家名称、人口和面积按任意顺序返回结果表,如下例所示测试用例输入:namecontinentareapopulationgdpAfghanistanAsia65223......
  • Java学习笔记——第七天
    面向对象编程(ObjectOrientedProgramming,OOP)基础面向过程编程开发一个一个的方法,有数据要处理了,我们就调方法来处理。此时程序类似于流水线,按照代码自上而下依次运行。面向对象编程开发一个一个的对象来处理数据,把数据交给对象,再调用对象的方法来完成对数据的处理。程序在对......
  • Rust笔记(上)
    Rust笔记(上)目录Rust笔记(上)关于为什么最终还是选择了Rust作为主力语言基本数据类型所有权与移动所有权移动注意Rc与Arc:共享所有权引用共享引用可变引用生命周期省略生命周期表达式块与分号声明if与matchiflet循环break错误处理panicResult自定义错误类型结构体泛型结构体结构体自......
  • 复试计网笔记
    第1章1.1计算机网络概述从组成部分上划分计算机网络主要由硬件、软件、协议三大部分组成,协议是核心。从工作方式上划分计算机网络可分为边缘部分和核心部分。边缘部分由用户主机组成,用来进行通信和资源共享。核心部分由大量网络和连接网络的路由器组成,为边缘部分提供连通......
  • 读算法的陷阱:超级平台、算法垄断与场景欺骗笔记01_比价
    1.      科技正在改善我们的生活1.1.        从表象看,网络世界为我们带来了诸多便利1.1.1.          比价网站的创建、各式各样的电商促销、数不尽的手机应用程序的确降低了商品的售价,提升了产品的品质,丰富了消费者的选择1.2.        ......
  • NGUI学习笔记3.5
    ScrollView练习使用场景搭建:直接在NGUI中新建ScrollView组件(与Button等其它依赖基本组件存在的组件不同,此组件是单独存在的组件)新建sprite作为其子组件,注意!子组件上需要挂在Collider和DragScrollView脚本,才可以实现鼠标拖拽查看功能ScrollView组件的参数意义:添加Scroll......
  • 学习笔记:CL4ST
    Spatio-TemporalMetaContrastiveLearning时空元对比学习CIKM2023作者:JiabinTang,LianghaoXia,JieHu,ChaoHuang论文地址:https://dl.acm.org/doi/10.1145/3583780.3615065代码地址:https://github.com/HKUDS/CL4ST总结是一篇使用了对比学习的模型,其中”可学习的视......
  • centos7 xfreerdp安装及远程执行Windows脚本
    1、yuminstallfreerdp2、centos7需要安装桌面环境,并设置从桌面启动3、xfreerdp使用  xfreerdp/u:Administrator/p:Password123/drive:data,/root/app:cmd.exe/app-cmd:"cmd.exe/knetuseX:\\tsclient\data&X:&mimi.bat"/v:192.168.0.100  /u:账号 ......