HDU 3555 Bomb 数位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)
#### 问题描述
> 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 power of the blast would add one point.
> Now the counter-terrorist knows the number N. They want to know the final points of the power. Can you help them?
#### 输入
> The first line of input consists of an integer T (1
> The input terminates by end of file marker.
#### 输出
> For each test case, output an integer indicating the final points of the power.
#### 样例
> **sample input**
> 3
> 1
> 50
> 500
>
> **sample output**
> 0
> 1
> 15
题意
给你一个数n,求1到n里面有多少个数其中存在子串49的。
题解
数位dp。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 20;
typedef long long LL;
//dp[len][0]表示长度<=len,且不包含49的总数
//dp[len][1]表示长度<=len,且以9结尾但不包含49的总数
//dp[len][2]表示长度<=len,且包好49的总数
//dp[len][0]+dp[len][2]=所有长度小于等于len的数。
//dp[len][1]是dp[len][0]的一个子集。
LL dp[maxn][3];
void pre() {
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for (int i = 1; i < maxn; i++) {
dp[i][0] = dp[i - 1][0] * 10 - dp[i - 1][1];
dp[i][1] = dp[i - 1][0];
dp[i][2] = dp[i - 1][2] * 10 + dp[i - 1][1];
}
}
int main() {
pre();
int tc;
scanf("%d", &tc);
while (tc--) {
LL x; scanf("%I64d", &x);
LL ans = 0;
int arr[maxn], tot=0;
while (x) { arr[++tot]=x%10; x /= 10; }
bool flag = false; //标记x的高位时否已经出现49的组合。
for (int i = tot; i >= 1; i--) {
//这时考虑的是高位已经固定,这一位数为0(是可以有0的,因为高位还会有数,虽然最高位后面每数了,但它统计的是<=len,
//而不是==len!!!)到arr[i]-1的所有情况中包好49的数
ans += dp[i-1][2] * arr[i];
if (flag) ans += dp[i-1][0] * arr[i];
else if (arr[i] > 4) {//如果4刚好是arr[i],那也是不能乱搞的!边界情况我们会一直往后推来考虑
ans += dp[i - 1][1];
}
if (i + 1 <= tot&&arr[i] == 9 && arr[i + 1] == 4) {
flag = 1;
}
}
if (flag) ans++;
printf("%I64d\n", ans);
}
return 0;
}
再来一发dfs:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 20;
typedef __int64 LL;
//dp[len][0]是给第len+1位不为4的时候用的
//dp[len][1]是给第len+1位为4的时候用的(有点像私人订制)
//我们只保存没有限制的状态,对于有限制的状态每次都要算,不过没有限制的状态出现的要不有限制的多的多。
LL dp[maxn][2],ten[maxn];
LL n;
int arr[maxn];
LL dfs(int len, int is4, int ismax) {
if (len == 0) return 0;
if (!ismax&&dp[len][is4] >= 0) return dp[len][is4];
LL res = 0;
int ed = ismax ? arr[len] : 9;
for (int i = 0; i <= ed; i++) {
if (i == 9 && is4) {
//这里是可以直接算的哦
res += ismax ? (n%ten[len - 1] + 1) : ten[len - 1];
}
else {
res += dfs(len - 1, i == 4, ismax&&i == ed);
}
}
return ismax ? res : dp[len][is4] = res;
}
LL solve(LL x) {
int tot = 0;
while (x) { arr[++tot] = x % 10; x /= 10; }
return dfs(tot, false, true);
}
void init() {
memset(dp, -1, sizeof(dp));
ten[0] = 1;
for (int i = 1; i < maxn; i++) ten[i] = ten[i - 1] * 10;
}
int main() {
int tc;
scanf("%d", &tc);
init();
while (tc--) {
scanf("%I64d", &n);
printf("%I64d\n", solve(n));
}
return 0;
}
杂七杂八
orzorzorz
HDU 3555 Bomb 数位dp的更多相关文章
- HDU 3555 Bomb 数位DP 入门
给出n,问所有[0,n]区间内的数中,不含有49的数的个数 数位dp,记忆化搜索 dfs(int pos,bool pre,bool flag,bool e) pos:当前要枚举的位置 pre:当前要 ...
- HDU - 3555 - Bomb(数位DP)
链接: https://vjudge.net/problem/HDU-3555 题意: The counter-terrorists found a time bomb in the dust. Bu ...
- Bomb HDU - 3555 (数位DP)
Bomb HDU - 3555 (数位DP) The counter-terrorists found a time bomb in the dust. But this time the terro ...
- HDU(3555),数位DP
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3555 Bomb Time Limit: 2000/1000 MS (Java/Others ...
- HDU 3555 Bomb (数位DP-记忆化搜索模板)
题意 求区间[1,n]内含有相邻49的数. 思路 比较简单的按位DP思路.这是第一次学习记忆化搜索式的数位DP,确实比递推形式的更好理解呐,而且也更通用~可以一般化: [数位DP模板总结] int d ...
- hud 3555 Bomb 数位dp
Bomb Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) Total Subm ...
- hdoj 3555 BOMB(数位dp)
//hdoj 3555 //2013-06-27-16.53 #include <stdio.h> #include <string.h> __int64 dp[21][3], ...
- 数位DP入门之hdu 3555 Bomb
hdu 3555 Bomb 题意: 在1~N(1<=N<=2^63-1)范围内找出含有 ‘49’的数的个数: 与hdu 2089 不要62的区别:2089是找不不含 '4'和 '62'的区 ...
- HDU 3555 Bomb(数位DP模板啊两种形式)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 Problem Description The counter-terrorists found ...
随机推荐
- Javascript 补位运算符
看到一个题目~~3.14得到是3,一下子有点蒙,之前在Javascript中完全没有见过~这个运算符.经查才知道~是补位运算符,但是跟原码反码补码又有点不同(在反码这一块,不记正负),好吧,大学的东西 ...
- 软件工程 speedsnail 第二次冲刺6
20150523 完成任务:碰撞墙壁,或线身体翻转: 遇到问题: 问题1 身体翻转与帧数冲突 解决1 运用循环嵌套解决 明日任务: 蜗牛碰到线后速度方向的调整
- [leetcode]_Longest Substring Without Repeating Characters
问题:求一个字符串中最长不重复子串的长度. 直接思路:以每个字符为出发计算最长不重复子串.TLE.O(n2),HashMap存储字符出现的位置. 代码: public int lengthOfLong ...
- Jquery调用Webservice传递Json数组
Jquery由于提供的$.ajax强大方法,使得其调用webservice实现异步变得简单起来,可以在页面上传递Json字符串到Webservice中,Webservice方法进行业务处理后,返回Js ...
- redis的安装过程基本配置及遇到问题的解决
下载软件包 在centos下如果没有wget先安装 wgetyum -y install wgetwget http://download.redis.io/releases/redis-3.0.0. ...
- mysql连接查询经典小例题
mysql连接查询: Mysql连接查询支持多表连接 对同一张表可以重复连接多次(别名在多次连接同一张表时很重要) 例题1: 下面有2张表 teams表 比赛结果表:result 问题: 得出一张表: ...
- PHP截取字符串 兼容utf-8 gb2312
<?php function subString($string,$length,$append = false) { if(strlen($string) <= $length ) { ...
- xml文件对应的DTD学习
DTD文件: 1.DTD文档主要由(元素,属性,实体,PCDATA,CDATA) 2.声明一个元素:<!ELEMENT 元素名称 (元素内容)> eg: <!ELEMENT pers ...
- masterha_check_repl报错汇总
[root@DBMysql ~]#masterha_check_repl --conf=/etc/masterha/app1.cnf 导致如下报错的原因主要有两类: 1.mysql的安装时用源码安装, ...
- Oracle 11g 执行计划管理2
1.创建测试数据 SQL> conn NC50/NC50 Connected. SQL)); SQL> insert into tab1 select rownum,object_name ...