不要62 HDU - 2089 (简单数位DP)

杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。 
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。 
不吉利的数字为所有含有4或62的号码。例如: 
62315 73418 88914 
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。 
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。 

Input

输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。 

Output

对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。 

Sample Input

1 100
0 0

Sample Output

80

题意如题目

解题方法:数位DP

这是一道较为简单的数位DP裸题,虽说简单,但是一开始理解起来会很困难

题中说要在给定集合里找到不满足条件的数的个数,当数据范围比较大的时候,暴力是一定不可能的

这时候我们利用数位DP来解决此类问题

首先,我们已知[a, b],那么可以将这个区间分解成[0, a]和[0, b],那么只需求[0, b] - [0, a - 1]之间满足的数的个数即可

然后将a和b的每一位的数存到数组a中各个元素,并得到位数length,然后再定义一个二维dp数组

至此,准备工作完成

接下来,我们进行记忆化搜索,利用深度优先搜索的原理,记录上一位是否为6和枚举这一位,如果没有限制的话很好办,直接枚举就可以了,但是这样可能会超空间,因此我们每次都必须要判断是否有最大的限制,比如说最大是455,那么百位的遍历范围只有0到4,十位和个位同理,当没有限制时遍历直接0到9,同时已经计算过的状态不会计算第二次,深度优先遍历到最底层、然后向上传递返回值,满足条件的会存放到dp数组中,定义一个变量计算它们的和,函数参数设定以及dp数组设定不唯一,具体见代码

代码:

#include <iostream>  
#include <cstring>
#include <cstdio>
#include <algorithm>  

using namespace std;

int a, b, shu[100];
long long dp[20][2];

long long dfs(int len, int pre, int state, bool limit){
	if(len == -1)
		return 1;
	if(!limit && dp[len][state] != -1)
		return dp[len][state];
	int maxq = limit ? shu[len] : 9;
	long long ans = 0;
	for(int i = 0; i <= maxq; i++){
		if(pre == 6 && i == 2)
			continue;
		if(i == 4)
			continue;
		ans += dfs(len - 1, i, i == 6 ? 1 : 0, limit && i == shu[len]);
	}
	if(!limit)
		dp[len][state] =ans;
	return ans;
}

int solve(int x){
	memset(shu, 0, sizeof(shu));
	int k = 0;
	while(x){
		shu[k++] = x % 10;
		x /= 10;
	}
	return dfs(k - 1, 0, 0, true);
}

int main()
{
	while(scanf("%d%d", &a, &b) && a != 0 && b != 0){
		memset(dp, -1, sizeof(dp));
		cout << solve(b) - solve(a - 1) << endl;
	}
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值