首页 > 其他分享 >数位DP?记忆化罢了!

数位DP?记忆化罢了!

时间:2023-06-17 17:35:24浏览次数:44  
标签:int dfs 记忆 我们 DP 数位

我看了半天的数位 DP,DP 没学会,人倒是麻了。

解决什么

一般用于求解给你一个区间 \([l,r]\),问你其中满足条件的数有多少个。

这种题目还是蛮常见的,我们一般情况下暴力只能拿一少部分分,之前我看着那个 \(n\le 10^{18}\) 是一脸懵逼,这东西 \(O(n)\) 都过不去,啥高级的东西能 A 啊。

然后就有了今天让我麻了的数位 DP。

思想

题目中给的让我们难以下手,我们不如转化一下:求 \([1,r]\) 中符合限制的数并减去 \([1,l-1]\) 的数。

这样就好处理多了,当然也可以从 \(0\) 开始,根据题目而定。

然后我们把要求的 \([1,x]\) 区间中的 \(x\) 给一位一位分解开,然后 dfs 往里面填数。

在分解的时候,我们用一个数组 \(a[i]\) 来存储从高位到低位(一般是)的数字,来当作填数的限制。

我们在 dfs 的时候,传的参数至少是包含 pos 当前填到第几个数以及 limit 也就是当前点是否有限制,如果有的话,我们在后面遍历当前点填的数的时候直接调用之前的 \(a[]\) 数组就好了。

当然我们在 dfs 的时候是要记忆化的,不然复杂度直接飙升,我们可以根据题目给的限制条件来把状态相同的归到一类然后存放到数组里面,然后我们就可以在遇到与当前状态相同的时候直接调用记忆化数组来让我们的复杂度变得美丽。

遍历每一个数的时候一般分为两种情况,一个有前导零,一个没有前导零。

P2602 [ZJOI2010] 数字计数

code:

#include <bits/stdc++.h>

#define int long long
#define N 20

using namespace std;

int a[N], cnt, f[N][N << 3][2][2], dight; 

inline int dfs(int p, int cntd, int lead, int limit)//p是当前位置,cntd是当前答案lead是有没有前导零。limit是当前数字枚举到的数量上限 
{
	if(p == cnt) return cntd;//到了就直接返回搜到的值 
	if(f[p][cntd][lead][limit] != -1) return f[p][cntd][lead][limit];//记忆化,以前搜过了就直接返回 
	int ans = 0;//统计答案 
	for(int v = 0; v <= (limit ? a[p] : 9); v ++)//枚举当前点可以是哪些数字 
	{
		if(lead && v == 0)//如果要是当前点有前导零,并且当前的点的下一个枚举的是0 
			ans += dfs(p + 1, cntd, 1, limit && v == a[p]);//答案累加,计算当前状态下的答案标记有前导零 
		else
			ans += dfs(p + 1, cntd + (v == dight), 0, limit && v == a[p]);//正常情况 
	}
	return f[p][cntd][lead][limit] = ans;//返回答案的同时记忆化 
}

inline int fx(int x)
{
	cnt = 0;
	memset(f, -1 , sizeof f);
	memset(a, 0, sizeof a);//清空数组 
	while(x) a[cnt ++] = x % 10, x /= 10;//由低位到高位 
	reverse(a, a + cnt);//反转一下让他顺序变正常 
	return dfs(0, 0, 1, 1);//开始搜索 前面有0并且第一个数是有限制的 
}

signed main()
{
	int L, R;
	cin >> L >> R;
	
	for(int i = 0; i <= 9; i ++)//枚举九个数字 
	{
		dight = i;//更新dight的值 
		cout << fx(R) - fx(L - 1) << " ";//跑一遍输出当前数字出现的次数 
	}
	
	return 0;
}

和前面讲的一样,利用记忆化搜索,注释应该很清楚了吧。

标签:int,dfs,记忆,我们,DP,数位
From: https://www.cnblogs.com/Multitree/p/17487561.html

相关文章

  • 斜率优化dp 学习笔记
    斜率优化dp引入首先,我们考虑一种更简单的dp优化——单调队列优化。比如,一个dp式形如:\[dp_{i}=\min_{k\leqj\leqi}(dp_j+f_j+g_i)\]我们发现,这个式子可以通过拆分(wgj:分离变量),变形成如下式子:\[dp_{i}=\min_{k\leqj\leqi}(dp_j+f_j)+g_i\]怎么样?我们发现,取最小......
  • Wordpress:Briefly unavailable for scheduled maintenance. Check back in a minute.
    场景描述:在更新Wordpress版本从Version6.2.1升级到Version6.2.2时候,顺带点升级的插件太多了,突然就崩溃报错:Brieflyunavailableforscheduledmaintenance.Checkbackinaminute。 因为用的是Siteground建站,以为过会就好了,等了五分钟还是这样,所以进Siteground后台,文件管......
  • 如何在WORDPRESS中添加CNZZ等统计代码
    1,   首先进入我们的WordPress网站后台,即在浏览器上输入网站域名/wp-login,如我的网站是输入forlong401.com/wp-login,然后输入用户名及密码,进入后台,点击左侧的“外观->主题”,查看一下我们使用的是什么主题,像我的进入后台后,会发现有三个主题可供选择,一个TwentyThirteen、Twenty......
  • 教你如何完美更改wordpress站域名
    最近因为要把博客网站从nas上搬运到阿里云服务器,又重温了一遍如何完美搬迁wordpress整站。其实搬运wordpress博客无非就是以下两种情况:1.更换服务器,不换域名2.更换域名下面我分别介绍一下如何完美搬迁wordpress博客1.更换服务器,不换域名这种情况下相对比较简单,三步即可备......
  • js保留小数位数(进位舍去)问题
    toFixed(x)这个方法在使用时,它内部对于进位舍去并没有使用四舍五入方法,而是使用的是银行家舍去法,即:舍去位的数值小于5时,直接舍去舍去位的数值大于等于6时,进位舍去当舍去位的数值等于5时,分为两种情况:5后面还有其他数字(非0),则进位后舍去;若5后面是0,则根据5前一位数的奇偶性来......
  • 【剑指Offer】13、调整数组顺序使奇数位于偶数前面
    【剑指Offer】13、调整数组顺序使奇数位于偶数前面题目描述:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。解题思路:首先,如果不考虑奇数和奇数,偶数和偶数......
  • 客服端与服务端在TCP/UDP的执行顺序的感受与想法
    网络层与传输层是从上到下还是从下到上网络通信的核心是socket套接字的创建,创建离不开一个关键的点,IP和端口。网络层:提供了端对端的传输,可以理解为通过IP寻址机器。传输层:决定机器的哪一个进程去处理,通过端口寻址。逻辑思维都是,我们通讯一个设备,首先要知道它的IP地址,然后确定......
  • Doosan Excavator Inspection Diagnostic Tool DDT SCR DPF G2 Scan DCU ECU DMS-5 Ha
    DoosanExcavatorInspectionDiagnosticToolDDTSCRDPFG2ScanDCUECUDMS-5Hardware+Software2022.09Softwaredownloadlink:https://mega.nz/file/Bk8X1QxA#g49TrmFsIljfHQpAIkQlG-VIWSgug8kLq3VffqAW00YHardware+SoftwareVersionDoosanDDTSCRDoosan......
  • Longest Path (牛客多校) (换根DP+斜率优化)
    换根dp:第一次dfs处理儿子点的权值第二次dfs处理父亲点,和兄弟节点的权值处理兄弟节点的时候,利用父亲节点统一处理,利用stl存储斜率优化:为什么会用到斜率优化:在遇到转移式子是fixfj的时候,不是分开的,(分开的,直接用单调队列处理)(通常会遇到平方式子)把......
  • ScheduledThreadPoolExecutor模仿学习
     publicinterfaceCBlockingQueue<E>{booleanadd(Ee);Etake();} importjava.util.concurrent.Delayed;importjava.util.concurrent.FutureTask;importjava.util.concurrent.RunnableScheduledFuture;importjava.util.concurrent.TimeUnit;......