HDU 3555 Bomb (数位DP)

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数,它是按位来进行计数统计的,可以保存子状态,速度较快。数位dp做多了后,套路基本上都差不多,关键把要保存的状态给抽象出来,保存下来。

简介:

顾名思义,所谓的数位DP就是按照数字的个,十,百,千……位数进行的DP。
数位DP的题目有着非常明显的性质:

询问[l,r]的区间内,有多少的数字满足某个性质

做法根据前缀和的思想,求出[0,l-1][0,r]中满足性质的数的个数,然后相减即可。

算法核心:

关于数位DP,貌似写法还是比较多的,有递归的,也有非递归的。
下面学习一下较好理解,可拓展性较高的递归写法。

LL dfs(int x,int pre,int bo,int limit);

一般需要以上参数(当然具体情况具体分析)。

  • x表示当前的数位(一般都是从高位到低位

  • pre表示前一位的数字
  • bo可以表示一些附加条件:是否有前项0,是否包含49,是否当前已经符合条件……
  • limit这个很重要!它表示当前数位是否受到上一位的限制,比较抽象,举例说明
    如果上限是135,前两位已经是1和3了,现在到了个位,个位只能是5以下的数字

注:如果当前受限,不能够记忆化,也不能返回记忆化的结果
为了避免多次调用时 每次上限不同 而导致的错乱影响

例题:HDU 3555

题意:a到b中有多少个数字包含49

思路:

dfs(x,pre,bo,limit)
表示当前位置,前一位的数字,当前是否已经包含49,以及是否有上界
当然,直接搜索肯定TLE,f[x][pre][bo]记忆化即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N = 20;
#define LL long long
int dig[N];
LL f[N][10][2];
//  数位,前一位数,是否符合条件,是否符合限制 [从高位到低位处理]
LL dfs(int x, int pre, int bo, int limit){
	if (x < 0) return bo; // 已经枚举了最后一位
	if (!limit && f[x][pre][bo] != -1) return f[x][pre][bo]; // 记忆化dp
	int last = limit ? dig[x] : 9; // 确定这一位的上限是多少
	LL re = 0;
	for (int i = 0; i <= last; i++)
		re += dfs(x - 1, i, bo || (pre == 4 && i == 9), limit && (i == last));
	if (!limit) f[x][pre][bo] = re; // 当前受限,不能够记忆化,也不能返回记忆化的结果
	return re;
}
LL solve(LL n){
	int len = 0;
	while (n){
		dig[len++] = n % 10;
		n /= 10;
	}
	return dfs(len - 1, 0, 0, 1);
}
int main(){
	memset(f, -1, sizeof(f));
	int T; scanf("%d", &T);
	while (T--){
		LL n;
		cin >> n;
		cout << solve(n) << endl;
	}
	return 0;
}
时间: 2024-10-18 16:43:38

HDU 3555 Bomb (数位DP)的相关文章

[ACM] hdu 3555 Bomb (数位DP,统计1-N中含有“49”的总数)

Bomb Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 7187 Accepted Submission(s): 2512 Problem Description The counter-terrorists found a time bomb in the dust. But this time the terrorists impro

HDU 3555 Bomb(数位DP)

Description The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, Paper, Stone' (also known as 'Rock, Paper, Scissors', 'Ro, Sham, Bo', and a host of other names) in order to make arbitrary decisions such as who gets

HDU(3555),数位DP

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3555 Bomb Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 15372    Accepted Submission(s): 5563 Problem Description The counter-terrorists f

hdu 3555(数位dp 入门)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 Bomb Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 7716    Accepted Submission(s): 2702 Problem Description The counter-terrorists found a

hud 3555 Bomb 数位dp

Bomb Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 19122    Accepted Submission(s): 7068 Problem Description The counter-terrorists found a time bomb in the dust. But this time the terrorist

HDU 3555 Bomb [数位]

Description The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the time bomb. The number sequence of the time bomb counts from 1 to N. If the current number sequence includes the sub-sequence "49", the

hdu 3555 Bomb(数位dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 题目大意:就是给你一个数n,判断从0到n有多少个数含有数字49...... 是不是觉得跟hdu2089很相似呀... 思路:跟hdu2089一样的,注意给出的数比较大,所以这儿用__int64  .... code: #include<cstdio> #include<iostream> #include<cstring> #include<algorithm&

HDU - 3555 Bomb (数位DP)

题意:求1-n里有多少人包含"49"的数字 思路:数位DP,分三种情况:到第i位没有49的情况,到第i位没有49且最高位是9的情况,到第i位有49的情况,将三种情况都考虑进去就是了 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; long long dp[30][3], n; int arr

HDU 3555——Bomb

HDU 3555——Bomb 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3555 题意:让你找找不大于n的数里有多少含‘49’, 我们发现,T很大,N很大,暴力指定不行,因为含不含'49'是每一位的性质,可以考虑数位dp,(况且这就是数位dp的模板形式啊喂),因为在模板的基础改的,所以找的是1-n有多少个数不含49,总数减一下就行 dp状态记为dp[当前是第几位][前一位是不是4],所以第二维开到2就够用啦 模板题,上代码 1 #include<