题目链接:

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。

代码

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<vector>
  5. using namespace std;
  6. const int maxn = 20;
  7. typedef long long LL;
  8. //dp[len][0]表示长度<=len,且不包含49的总数
  9. //dp[len][1]表示长度<=len,且以9结尾但不包含49的总数
  10. //dp[len][2]表示长度<=len,且包好49的总数
  11. //dp[len][0]+dp[len][2]=所有长度小于等于len的数。
  12. //dp[len][1]是dp[len][0]的一个子集。
  13. LL dp[maxn][3];
  14. void pre() {
  15. memset(dp, 0, sizeof(dp));
  16. dp[0][0] = 1;
  17. for (int i = 1; i < maxn; i++) {
  18. dp[i][0] = dp[i - 1][0] * 10 - dp[i - 1][1];
  19. dp[i][1] = dp[i - 1][0];
  20. dp[i][2] = dp[i - 1][2] * 10 + dp[i - 1][1];
  21. }
  22. }
  23. int main() {
  24. pre();
  25. int tc;
  26. scanf("%d", &tc);
  27. while (tc--) {
  28. LL x; scanf("%I64d", &x);
  29. LL ans = 0;
  30. int arr[maxn], tot=0;
  31. while (x) { arr[++tot]=x%10; x /= 10; }
  32. bool flag = false; //标记x的高位时否已经出现49的组合。
  33. for (int i = tot; i >= 1; i--) {
  34. //这时考虑的是高位已经固定,这一位数为0(是可以有0的,因为高位还会有数,虽然最高位后面每数了,但它统计的是<=len,
  35. //而不是==len!!!)到arr[i]-1的所有情况中包好49的数
  36. ans += dp[i-1][2] * arr[i];
  37. if (flag) ans += dp[i-1][0] * arr[i];
  38. else if (arr[i] > 4) {//如果4刚好是arr[i],那也是不能乱搞的!边界情况我们会一直往后推来考虑
  39. ans += dp[i - 1][1];
  40. }
  41. if (i + 1 <= tot&&arr[i] == 9 && arr[i + 1] == 4) {
  42. flag = 1;
  43. }
  44. }
  45. if (flag) ans++;
  46. printf("%I64d\n", ans);
  47. }
  48. return 0;
  49. }

再来一发dfs:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<vector>
  5. using namespace std;
  6. const int maxn = 20;
  7. typedef __int64 LL;
  8. //dp[len][0]是给第len+1位不为4的时候用的
  9. //dp[len][1]是给第len+1位为4的时候用的(有点像私人订制)
  10. //我们只保存没有限制的状态,对于有限制的状态每次都要算,不过没有限制的状态出现的要不有限制的多的多。
  11. LL dp[maxn][2],ten[maxn];
  12. LL n;
  13. int arr[maxn];
  14. LL dfs(int len, int is4, int ismax) {
  15. if (len == 0) return 0;
  16. if (!ismax&&dp[len][is4] >= 0) return dp[len][is4];
  17. LL res = 0;
  18. int ed = ismax ? arr[len] : 9;
  19. for (int i = 0; i <= ed; i++) {
  20. if (i == 9 && is4) {
  21. //这里是可以直接算的哦
  22. res += ismax ? (n%ten[len - 1] + 1) : ten[len - 1];
  23. }
  24. else {
  25. res += dfs(len - 1, i == 4, ismax&&i == ed);
  26. }
  27. }
  28. return ismax ? res : dp[len][is4] = res;
  29. }
  30. LL solve(LL x) {
  31. int tot = 0;
  32. while (x) { arr[++tot] = x % 10; x /= 10; }
  33. return dfs(tot, false, true);
  34. }
  35. void init() {
  36. memset(dp, -1, sizeof(dp));
  37. ten[0] = 1;
  38. for (int i = 1; i < maxn; i++) ten[i] = ten[i - 1] * 10;
  39. }
  40. int main() {
  41. int tc;
  42. scanf("%d", &tc);
  43. init();
  44. while (tc--) {
  45. scanf("%I64d", &n);
  46. printf("%I64d\n", solve(n));
  47. }
  48. return 0;
  49. }

杂七杂八

orzorzorz

HDU 3555 Bomb 数位dp的更多相关文章

  1. HDU 3555 Bomb 数位DP 入门

    给出n,问所有[0,n]区间内的数中,不含有49的数的个数 数位dp,记忆化搜索 dfs(int pos,bool pre,bool flag,bool e) pos:当前要枚举的位置 pre:当前要 ...

  2. HDU - 3555 - Bomb(数位DP)

    链接: https://vjudge.net/problem/HDU-3555 题意: The counter-terrorists found a time bomb in the dust. Bu ...

  3. Bomb HDU - 3555 (数位DP)

    Bomb HDU - 3555 (数位DP) The counter-terrorists found a time bomb in the dust. But this time the terro ...

  4. HDU(3555),数位DP

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3555 Bomb Time Limit: 2000/1000 MS (Java/Others ...

  5. HDU 3555 Bomb (数位DP-记忆化搜索模板)

    题意 求区间[1,n]内含有相邻49的数. 思路 比较简单的按位DP思路.这是第一次学习记忆化搜索式的数位DP,确实比递推形式的更好理解呐,而且也更通用~可以一般化: [数位DP模板总结] int d ...

  6. hud 3555 Bomb 数位dp

    Bomb Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Subm ...

  7. hdoj 3555 BOMB(数位dp)

    //hdoj 3555 //2013-06-27-16.53 #include <stdio.h> #include <string.h> __int64 dp[21][3], ...

  8. 数位DP入门之hdu 3555 Bomb

    hdu 3555 Bomb 题意: 在1~N(1<=N<=2^63-1)范围内找出含有 ‘49’的数的个数: 与hdu 2089 不要62的区别:2089是找不不含 '4'和 '62'的区 ...

  9. HDU 3555 Bomb(数位DP模板啊两种形式)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 Problem Description The counter-terrorists found ...

随机推荐

  1. ASP.NET中的状态保持(转载)

    状态是某一类型的数据在一定时期内保持活跃的信息.这里说的一定时期可以使整个应用程序的生命周期,可以使用户操作程序的时间,当然也可以是单个页面的生命周期等.  为了解决传统Web编程中固有的限制,ASP ...

  2. SMTP sendMail 失败解决办法

    If you are seeing messages like this in your message log when running a process through the process ...

  3. MongoDb 与 Nodejs服务器的启动

    1) 启动MongoDB : MongoDB —dbpath databaseNameFolder. 2) 启动数据库 : Mongo DatabaseName. 3) 启动NodeJs: Node ...

  4. Service(一)----->简单计算

    xml: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:t ...

  5. 【原】简述使用spark集群模式运行程序

    本文前提是已经正确安装好scala,sbt以及spark了   简述将程序挂载到集群上运行的步骤: 1.构建sbt标准的项目工程结构: 其中: ~/build.sbt文件用来配置项目的基本信息(项目名 ...

  6. SIMATIC PCS 7 结构图

  7. jQuery学习笔记(5)--表单域获得焦点和失去焦点样式变化

    <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> &l ...

  8. Pure扩展站--个人博客

    作为自己css的练习站:http://1111.oyostar.com/.更新自己扩展pure写的css,外加一些jquery的插件.感谢朋友的空间和子域名!

  9. apache 403错

    <Directory />Options FollowSymLinksAllowOverride NoneOrder deny,allowAllow from all</Direct ...

  10. rails中ActionController::InvalidAuthenticityToken解决办法

    Ror代码 class FooController < ApplicationController protect_from_forgery :except => :index # you ...