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 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?

Input

The first line of input consists of an integer T (1 <= T <= 10000), indicating the number of test cases. For each test case, there will be an integer N (1 <= N <= 2^63-1) as the description.

The input terminates by end of file marker.

Output

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

Hint

From 1 to 500, the numbers that include the sub-sequence "49" are "49","149","249","349","449","490","491","492","493","494","495","496","497","498","499",
so the answer is 15.

Author

[email protected]

参考:http://blog.csdn.net/ecjtu_yuweiwei/article/details/11835209

  1. /*
  2. 题意:求1~N中含有数字49的个数     1 <= N <= 2^63-1
  3. 方法:数位DP
  4. dp[len][0] 代表长度为len不含49的方案数
  5. dp[len][1] 代表长度为len不含49但是以9开头的数字的方案数
  6. dp[len][2] 代表长度为len含有49的方案数
  7. 状态转移如下
  8. dp[i][0] = dp[i-1][0] * 10 - dp[i-1][1];  //如果不含49且,在前面可以填上0-9 但是要减去dp[i-1][1] 因为4会和9构成49
  9. dp[i][1] = dp[i-1][0];  //这个直接在不含49的数上填个9就行了
  10. dp[i][2] = dp[i-1][2] * 10 + dp[i-1][1]; //已经含有49的数可以填0-9,或者9开头的填4
  11. 写完动态转移方程后就把N从高位到低位一个一个统计了
  12. 在统计到某一位的时候,加上 dp[i-1][2] * digit[i] 是显然没问题,这是因为这一位可以填【0,(digit[i]-1)】这个区间的数
  13. 若这一位之前挨着49,那么加上 dp[i-1][0] * digit[i] 也是显然OK。
  14. 若这一位之前没有挨着49,但是digit[i]比4大,那么当这一位填比digit[i]小的4的时候,就得加上dp[i-1][1](以9开头的数字的方案数)
  15. */

PS:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <cstdio>
#include <cmath>
typedef long long ll;
using namespace std;
ll dp[22][4];
ll digit[22];

void sove()
{
        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()
{
        ll  T,n;
        cin>>T;
        sove();
        while(T--)
        {
            scanf("%I64d",&n);
            memset(digit,0,sizeof(digit));
            int len=0;
            while(n)
            {
             digit[++len]=n%10;
             n/=10;
            }
            int flag=0,last=0;
            ll cnt=0;
            for(int i=len;i>=1;i--)
            {
                cnt+=dp[i-1][2]*digit[i];

                if(flag)
                        cnt+=dp[i-1][0]*digit[i];
                if(!flag&&digit[i]>4)
                        cnt+=dp[i-1][1];
                if(last==4&&digit[i]==9)
                        flag=1;
                last=digit[i];
            }
            if(flag)cnt++;
            printf("%I64d\n",cnt);
        }
  return 0;
}
时间: 2024-11-15 05:37:07

hdu 3555(数位dp 入门)的相关文章

HDU 3555 数位dp入门

开始想用dp[i][j]来记录第i位j开头含有49的数的个数 但是init后并不知道如何进行cal 想了想可以用不要62的思想 当作不要49来做 然后减一下 就好 看网上的代码 不要62和这道题用的dp方法和cal都与我用的有很大不同 做完入门水题就去学习一下那种很正规的方法~ #include<stdio.h> #include<string.h> #include<algorithm> #include<map> #include<math.h&g

HDU 2089 数位dp入门

开始学习数位dp...一道昨天看过代码思想的题今天打了近两个小时..最后还是看了别人的代码找bug...(丢丢) 传说院赛要取消 ? ... 这么菜不出去丢人也好吧~ #include<stdio.h> #include<string.h> #include<algorithm> #include<map> #include<math.h> #include<queue> using namespace std; int n,m; /

HDU 3555 数位dp

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

hdu 3555 数位dp水题 记忆化搜索做法

#include<iostream> #include<cstring> #include<cstdio> using namespace std ; const int maxn = 20; __int64 dp[maxn][3] ;//dp[i][flag] ,flag = 2,表示已经有49,flag == 1,表示没有49,这一位是4, int bit[maxn] ;    //flag == 0, 什么都没有 __int64 dfs(int pos , int

数位DP入门题 hdu 2089 hdu 3555

hdu 2089 不要62 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 题意:对于每次给出的一个区间,找出区间内多少个数字没有出现62和4. 思路: 数位DP入门题,对于dfs设置3个参数. 一个表示现在进行到第几位, 一个表示前一个标记状态,这里表示上一位是不是6. 一个表示是否现在是这位可以取到的最大的数字. 如果上一位是6,那么这位不可以取2.且当前位都不可以取4. 1 #include <bits/stdc++.h> 2 us

HDU 2089 不要62 数位DP入门

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

HDU 2089 不要62【数位DP入门题】

不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 56193    Accepted Submission(s): 21755 Problem Description 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer).杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可

hdu 4734 数位dp

http://acm.hdu.edu.cn/showproblem.php?pid=4734 Problem Description For a decimal number x with n digits (AnAn-1An-2 ... A2A1), we define its weight as F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1. Now you are given two numbers A and B, plea

hdu 4352 数位dp(最长上升子序列的长度为k的个数)

http://acm.hdu.edu.cn/showproblem.php?pid=4352 Problem Description #define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then carefully reading the entire description is very important. As the strongest fighting force in UESTC, xhxj grew

hdu 3709 数位dp(小思维)

http://acm.hdu.edu.cn/showproblem.php?pid=3709 Problem Description A balanced number is a non-negative integer that can be balanced if a pivot is placed at some digit. More specifically, imagine each digit as a box with weight indicated by the digit.