HDU3555【数位DP】
入门...还在学习中,先贴一发大牛博客
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555
题目大意:
给一个数字n,范围在1~2^63-1,求1~n之间含有49的数字有多少个。
思路:
经典的数位DP,学习了一下,看的别人的代码:http://www.cnblogs.com/luyi0619/archive/2011/04/29/2033117.html
状态转移:
dp[i][0]代表长度为 i 并且不含有49的数字的个数;
dp[i][1]代表长度为 i 并且不含有49,但是最高位是9的数字的个数;
dp[i][2]代表长度为 i 并且含有49的数字的个数。
数组 a[i] 从低位到高位存储 n 的每一位数字。
则:dp[i][0] = dp[i-1][0] * a[i] - dp[i-1][1]; 表示长度为 i 的不含有49的数字的个数等于长度为 i - 1 的不含有49的数字的个数*当前的数字,因为这个位置可以填0~a[i] - 1,然后再减去长度为 i - 1 的最高位是9的数字的个数,因为如果长度为 i - 1 的最高位是9的话,那么高一位就不能填4了,否则就组成了49。
dp[i][1] = dp[i-1][0]; 表示长度为 i 的并且不含有49同时最高位是9的数字的个数等于,长度为 i - 1 的不含有49的数字的个数,因为只要在它的高一位加上一个9就可以了。
dp[i][2] = dp[i-1][2] * a[i] + dp[i-1][1]; 表示长度为 i 的含有49的数字的个数等于,长度为 i - 1 的数字的个数*当前的数字,再加上长度为 i - 1 的并且不含有49同时最高位是9的数字的个数,因为这个时候,只要在高一位加上一个4就可以了,这样在最高的两位就组成了一个49。
做法是从数字的高位向低位扫描,对于第 i 位,
- 首先加上长度为 i - 1 的符合条件的数字个数;
- 再讨论以前是不是出现过49,如果出现过,就要再追加上长度为 i - 1 的不符合条件的数字的个数,因为以前已经有49了;
- 如果没有出现过,就要判断这一位是不是大于4呢,如果大于4,就要再追加上长度为 i - 1 的不含有49但是最高位是9的数字的个数,因为这个时候可以再这一位填4,因为它大于4嘛~;
- 然后就是判断一下,当前位和上一位是不是满足49,如果满足,标记出现了49了!为以后的判断做准备。
其实这个题目还有一个地方不懂,就是为什么要在输入 n 后,要把 n 加1。想了一下特例,比如输入49,按照上面的做法,在第3步,并不会把符合条件的数字加上,因为4不是严格大于4,最后的执行结果就是0,但是如果加上1之后,n就变成了50,这样第3步恰好可以执行,结果就是正确的了。但是对于一般的情况,还是不知道为什么要把n加1……o(╯□╰)o
这题还是卡了很久,照着别人的代码敲的,死活过不了,然后又找了一份代码:http://blog.csdn.net/acm_cxlove/article/details/7819907 才发现输入输出要用%I64d,这不是坑么……原来hdu要用%I64d,囧……
所以,有时候的bug不是算法或者代码有错误,看看你的输入输出吧!还有,类似的情况,比如,输入文件写错了……更悲剧了。。
#include <cstdio>
#include <stack>
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long LL; LL dp[25][3];
LL a[25];
unsigned long long n; void init()
{
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<21;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()
{
init();
int T;
scanf("%d",&T);
while(T--)
{
scanf("%I64d",&n);
n++;
int len=0;
memset(a,0,sizeof(a));
while(n)
{
a[++len]=n%10;
n/=10;
}
LL ans=0;
int last=0;
bool flag=false; for(int i=len;i>=1;--i)
{
ans+=dp[i-1][2]*a[i];//首先加上长度为 i - 1 的符合条件的数字个数;
if(flag) //以前是不是出现过49,如果出现过,就要再追加上长度为 i - 1 的不符合条件的数字的个数,因为以前已经有49了;
ans+=dp[i-1][0]*a[i];
if(!flag&&a[i]>4) //如果没有出现过,就要判断这一位是不是大于4呢,如果大于4,就要再追加上长度为 i - 1 的不含有49但是最高位是9的数字的个数,因为这个时候可以再这一位填4,因为它大于4嘛~;
ans+=dp[i-1][1];
if(last==4&&a[i]==9) //然后就是判断一下,当前位和上一位是不是满足49,如果满足,标记出现了49了!为以后的判断做准备。
flag=true;
last=a[i];
}
printf("%I64d\n",ans);
}
return 0;
}
HDU3555【数位DP】的更多相关文章
- hdu3555 数位dp
Bomb Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) Total Subm ...
- hdu3555数位dp基础
/* dp[i][0|1|2]:没有49的个数|最高位是9,没有49的个数|有49的个数 dp[i][0]=10*dp[i-1][0]-dp[i-1][1] dp[i][1]=dp[i-1][0] d ...
- hdu3555(数位DP dfs/递推)
Bomb Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submi ...
- 数位dp浅谈(hdu3555)
数位dp简介: 数位dp常用于求区间内某些特殊(常关于数字各个数位上的值)数字(比如要求数字含62,49): 常用解法: 数位dp常用记忆化搜索或递推来实现: 由于记忆化搜索比较好写再加上博主比较蒟, ...
- hdu3555 Bomb (记忆化搜索 数位DP)
http://acm.hdu.edu.cn/showproblem.php?pid=3555 Bomb Time Limit: 2000/1000 MS (Java/Others) Memory ...
- hdu---(3555)Bomb(数位dp(入门))
Bomb Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submi ...
- hdu3555 Bomb 数位DP入门
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 简单的数位DP入门题目 思路和hdu2089基本一样 直接贴代码了,代码里有详细的注释 代码: ...
- 【Hdu3555】 Bomb(数位DP)
Description 题意就是找0到N有多少个数中含有49. \(1\leq N \leq2^{63}-1\) Solution 数位DP,与hdu3652类似 \(F[i][state]\)表示位 ...
- 【hdu3555】Bomb 数位dp
题目描述 求 1~N 内包含数位串 “49” 的数的个数. 输入 The first line of input consists of an integer T (1 <= T <= 1 ...
- [Hdu3555] Bomb(数位DP)
Description 题意就是找0到N有多少个数中含有49. \(1\leq N \leq2^{63}-1\) Solution 数位DP,与hdu3652类似 \(F[i][state]\)表示位 ...
随机推荐
- Python中十六进制和字符串的转换(转载)
调用Python内置int()函数把该字串转为数字.以下为在Python解释器编程环境下的操作示范: 把十六进制的字串转为十进制数字:Python代码>>> print int('f ...
- 【windows phone】CollectionViewSource的妙用
在windows phone中绑定集合数据的时候,有时候需要分层数据,通常需要以主从试图形式显示.通常的方法是将第二个ListBox(主视图)的数据源绑定到第一个ListBox (从视图)的Selec ...
- 【BZOJ4561】[JLoi2016]圆的异或并 扫描线
[BZOJ4561][JLoi2016]圆的异或并 Description 在平面直角坐标系中给定N个圆.已知这些圆两两没有交点,即两圆的关系只存在相离和包含.求这些圆的异或面积并.异或面积并为:当一 ...
- Java之运行时异常与编译时异常区别
Java中用2种方法处理异常: 1.在发生异常的地方直接处理: 2.将异常抛给调用者,让调用者处理. Java异常可分为3种: (1)编译时异常:Java.lang.Exception (2)运行期异 ...
- Hadoop实战-MapReduce之倒排索引(八)
倒排索引 (就是key和Value对调的显示结果) 一.需求:下面是用户播放音乐记录,统计歌曲被哪些用户播放过 tom LittleApple jack YesterdayO ...
- 超实用的 Nginx 极简教程,覆盖了常用场景(转)
概述 安装与使用 安装 使用 nginx 配置实战 http 反向代理配置 负载均衡配置 网站有多个 webapp 的配置 https 反向代理配置 静态站点配置 搭建文件服务器 跨域解决方案 参考 ...
- sqlserver锁表查看
sp_lock--查询哪个进程锁表了,spid:进程ID,ObjId:对象ID EXEC sp_executesql N'KILL [spid]'--杀进程 select object_name([O ...
- ModuleNotFoundError: No module named 'numpy.core._multiarray_umath' ImportError: numpy.core.multiarray failed to import
出现以下错误:可能是因为你的numpy版本太低 更新numpy的版本 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --upgra ...
- shell动态变量
面对变量中嵌套变量,可以这么做 other_devops_ip="......." options='_ip' tennat_name='other_devops' tennat_ ...
- .PHP生成静态html文件的方法
1. [代码][PHP]代码 1,下面使用模版的一个方法! <?php $fp = fopen ("templets.html","a"); ...