首页 > 其他分享 >数位DP小记

数位DP小记

时间:2024-08-30 18:15:27浏览次数:3  
标签:int sum pos long 小记 include 我们 DP 数位

1.基础

1.1. 问题

数位 DP 解决的一般都是和数字相关的计数问题,常见的有 \(l \sim r\) 中有多少数符合某个关于数位的条件。

对于这种问题,我们都是先用前缀和转化成小于等于某个数的问题。

下面以 P2602 [ZJOI2010] 数字计数 为模板题。

1.2 记忆化搜索

我们先枚举每个数码。

我们考虑设一个状态 \((i,j,0/1,0/1)\) 表示当前处理到了第 \(i\) 位,已经填了 \(j\) 个当前数码,有无前导 \(0\),是否贴着上界。

我们发现,有前导 0 或者贴着上界的状态其实只会搜索到 1 次,所以我们只用记录 \(f(i,j)\) 表示 \((i,j,0,0)\) 状态的答案来进行记忆化搜素。

首先,如果 \(i = 0\),我们直接返回 \(j\)。

其次,如果已经计算过了,我们返回答案。

否则,我们根据是否贴着上界算一下这一位的范围,然后枚举每个数码。

枚举的过程中,我们需要特判 0 和前导 0 的情况。

得出答案后在记忆化并返回即可。

时间复杂度是位数乘以进制。

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 15;

int tmp, num[N] = {0};//表示当前处理的数字
long long f[N][N] = {{0}};//f[i][j] 表示处理到 i 已经有了 j 个 tmp,且没有前导 0 和最高位限制

long long dfs(int pos, int sum, bool hd, bool lim) {
	long long ans = 0ll;
	if (pos == 0)
		return sum;
	if (!hd && !lim && f[pos][sum] != -1)
		return f[pos][sum];
	int up = (lim ? num[pos] : 9);
	for (int i = 0; i <= up; i++) {
		if (i == 0 && hd)
			ans += dfs(pos - 1, sum, hd, lim && i == up);
		else if (i == tmp)
			ans += dfs(pos - 1, sum + 1, false, lim && i == up);
		else
			ans += dfs(pos - 1, sum, false, lim && i == up);
	}
	if (!hd && !lim)
		f[pos][sum] = ans;
	return ans;
}

long long slv(long long n) {
	int len = 0;
	while (n > 0)
		num[++len] = n % 10, n /= 10;
	memset(f, -1, sizeof f);
	return dfs(len, 0, true, true);
}

int main() {
	long long l, r;
	cin >> l >> r;
	for (int i = 0; i <= 9; i++) {
		tmp = i;
		cout << slv(r) - slv(l - 1) << " ";
	}
	return 0;
} 

1.3 适合多测的方法

我们从另一个角度看,每次我们相当于需要处理的就是一个数划分成的若干区间。关键就是上界。

所以我们可以直接最开始计算 \(f(i,j)\) 表示从低到高确定了 \(i\) 位,\(j\) 的总个数。

然后对于一个数,我们从高到低处理,枚举每一位用 dp 值计算出答案即可。

这样我们只用一遍 dp 就可以解决问题了。


标签:int,sum,pos,long,小记,include,我们,DP,数位
From: https://www.cnblogs.com/rlc202204/p/18389257

相关文章

  • 在Android开发中,如何使用SharedPreferences(简称SP)一个轻量级的数据存储方式
    目录全局SharedPreferences工具类代码说明:如何使用这个工具类?在Android开发中,SharedPreferences(简称SP)是一个轻量级的数据存储方式,常用于保存应用的配置信息或少量的数据。为了便于在全局使用,可以将其封装到一个工具类中。以下是一个带有详细中文注释的全局SharedPrefere......
  • 插入类型 DP 学习笔记
    插入类型DP形式多为nnn个元素无法重复使用,需要给定一个排列,满足一定条件或是求有多少个排列满足一定条件。nnn一般在100∼5×103100\sim5\times10^3100∼5×103左右。满足一些函数图像,类似于波浪函数,且答案与每个波浪和波浪的顶点有关(函数的xxx坐标为下标,yy......
  • 在中国使用wordpress建网站的主要有三类人
    在中国,使用WordPress建网站的主要有三类人:做IT技术程序员、海归人士和做外贸的老板。这三类人选择WordPress的原因可以从WordPress的多个优势中找到答案。做IT技术程序员选择WordPress的原因在于其高度的可扩展性和灵活性。WordPress的模块化设计和强大的插件生态系统使得程序......
  • 树形dp的各种应用题型与模板
    ///**//低落...最近做了以及看了树形dp这部分的知识,感觉有必要做一些整理,所以特来此地写下来。我将整理一些树形dp基本的模板与应用以及思想。1.树的直径:树上最长的链概念应该很好懂,那么现在来看看代码(简略版):#include<iostream>usingnamespacestd;structEDGE{ int......
  • wordpress跨境电商外贸独立站 常见获取流量方式
    在建立跨境电商外贸独立站时,获取流量的方法有很多种,以下是一些常见的方法:社交媒体营销:通过发布有吸引力的内容在Facebook、Instagram、Twitter等平台上。电子邮件营销:通过向潜在客户发送定制的电子邮件,包含特别优惠或新产品信息。搜索引擎优化(SEO):提高网站在搜索引擎中的排名,以......
  • CoreNext主题1.5.2免授权 | WordPress主题模板
    CoreNext主题1.5.2免授权 | WordPress主题模板探索无限可能:CoreNext主题1.5.2免授权WordPress主题模板在这个数字化的时代,网站已成为个人品牌和企业展示的窗口。对于那些追求独特风格和高效管理的用户来说,选择一个合适的WordPress主题模板至关重要。今天,我们将深入探讨Core......
  • Linux学习(15)-网络编程:滑动窗口、拥塞控制、udp
    本节学习内容1.滑动窗口(1.滑动窗口的作用2.如果如果接收端填充的接收窗口为0,发送端接下来怎么处理3.糊涂窗口综合征4.tcp中nagle算法是什么)2.拥塞控制3.udp协议特点及编程流程本节可能会用到的指令ifconfig查看自己的ip地址ping+ip地址验证通信是否连接netstat-natp显......
  • TCP/IP、UDP/IP协议
    参考链接1、OSI七层模型(1)OSI含义“OSI模型,即开放式通信系统互联参考模型(OpenSystemInterconnectionReferenceModel),是国际标准化组织(ISO)提出的一个试图使各种计算机在世界范围内互连为网络的标准框架,简称OSI。”(2)OSI定义了网络互连的七层模型(物理层、数据链路层、网络层......
  • 线程池ThreadPool, C++
    一、为什么要有线程池?线程池是一种用于管理和复用线程的机制。它可以提高程序的性能和效率,特别是在处理大量并发任务时。线程池中包含一定数量的线程,这些线程可以重复执行多个任务。当有任务需要执行时,可以将任务提交给线程池,线程池会选择一个可用的线程来执行任务。任务执行完......
  • 拉格朗日插值优化 DP 做题笔记
    本来想在洛谷题单里找斜率优化DP的,然后发现了一个拉格朗日插值优化DP的题单,就点进去尝试了一下。题单。于是先看了雨兔的题解,学了CF995F的做法,然后A了这个题。雨兔题解的链接和我的代码见CF上的提交记录。现在正在做后面的题。P3643[APIO2016]划艇\(a_i,b_i......