• 数位DP HDU3555


    Bomb

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
    Total Submission(s): 15025    Accepted Submission(s): 5427


    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
    fatboy_cw@WHU
     
    Source
     
    Recommend
    zhouzeyong   |   We have carefully selected several similar problems for you:  3554 3556 3557 3558 3559 
     
    题意:
      1~nz中包含49的数有几个。
    代码:
      1 /*
      2 本题与HDU2089相似,把那道题的代码改了一下找出了不含49的,然后用总数减去,简单粗暴,当然有更好的方法。
      3 */
      4 #include<iostream>
      5 #include<string>
      6 #include<cstdio>
      7 #include<cmath>
      8 #include<cstring>
      9 #include<algorithm>
     10 #include<vector>
     11 #include<iomanip>
     12 #include<queue>
     13 #include<stack>
     14 using namespace std;
     15 int t;
     16 long long dp[40][10],n;
     17 void init()
     18 {
     19     for(int i=1;i<22;i++)
     20     {
     21         for(int j=0;j<10;j++)
     22         {
     23             for(int k=0;k<10;k++)
     24             {
     25                 if(j==4&&k==9) continue;
     26                 dp[i][j]+=dp[i-1][k];
     27             }
     28         }
     29     }
     30 }
     31 long long insum(long long n)
     32 {
     33     long long sum=0;
     34     int lne=1,c[30]={0};
     35     while(n)
     36     {
     37         c[lne++]=n%10;
     38         n/=10;
     39     }
     40     for(int i=lne-1;i>0;i--)
     41     {
     42         for(int j=0;j<c[i];j++)   //j不能等于c[i],因为dp[i][j]中的j代表第i位取j时的总数,而j后面的数
     43                                   //要全部遍历一遍,这里j后面并非取全部数而是取到给出的数的后几位
     44         {
     45             if(j==9&&c[i+1]==4) continue;
     46             sum+=dp[i][j];
     47         }
     48         if(c[i]==9&&c[i+1]==4) break;
     49     }
     50     return sum;
     51 }
     52 int main()
     53 {
     54     scanf("%d",&t);
     55     while(t--)
     56     {
     57         memset(dp,0,sizeof(dp));
     58         dp[0][0]=1;
     59         cin>>n;
     60         n+=1;
     61         init();
     62         long long a=insum(n);
     63         cout<<n-a<<endl;
     64     }
     65     return 0;
     66 }
     67 
     68 /*
     69 别人的一个更好的方法。很难想到。
     70 */
     71 #include<iostream>
     72 #include<string>
     73 #include<cstdio>
     74 #include<cmath>
     75 #include<cstring>
     76 #include<algorithm>
     77 #include<vector>
     78 #include<iomanip>
     79 #include<queue>
     80 #include<stack>
     81 using namespace std;
     82 int t;
     83 long long dp[25][3],n; //dp[i][0]表示到第i位没有49的个数,dp[i][1]表示到第i位没有49但第i位是9的个数,
     84                        //dp[i]][2]表示到第i位包含49的个数。
     85 void init()
     86 {
     87     dp[0][0]=1;        //初始化
     88     dp[0][1]=0;
     89     dp[0][2]=0;
     90     for(int i=1;i<23;i++)
     91     {
     92         dp[i][0]=10*dp[i-1][0]-dp[i-1][1];  //到第i位没有49的个数等于第i位依次取0~9连上后面没有49的,
     93                                             //然后去掉第i位取4,i-1位为9的情况。
     94         dp[i][1]=dp[i-1][0];                //第i位是9时
     95         dp[i][2]=10*dp[i-1][2]+dp[i-1][1];  //到第i位包含49的个数等于第i位依次取0~9连上后面包含49的,
     96                                             //再加上第i位取4时,i-1位是9的情况。
     97     }
     98 }
     99 long long insum(long long n)
    100 {
    101     long long sum=0;
    102     int c[23]={0};
    103     int cnt=1;
    104     while(n)
    105     {
    106         c[cnt++]=n%10;
    107         n/=10;
    108     }
    109     bool flag=false;
    110     for(int i=cnt-1;i>0;i--)   //从高位到低位依次枚举
    111     {
    112         sum+=dp[i-1][2]*c[i];           //到第i-1位包含49,就加上0~c[i]个
    113         if(flag) sum+=dp[i-1][0]*c[i];
    114         else
    115         {
    116             if(c[i]>4) sum+=dp[i-1][1];  //如果第i位大于4了,并且i-1是9,则一定包含49.
    117         }
    118         if(c[i+1]==4&&c[i]==9) flag=true; //当从高位出现49之后后面dp[i][0]就无意义了,全加上
    119     }
    120     return sum;
    121 }
    122 int main()
    123 {
    124     scanf("%d",&t);
    125     {
    126         while(t--)
    127         {
    128             scanf("%lld",&n);
    129             init();
    130             printf("%lld
    ",insum(n+1));  //计算结果不包含n本身
    131         }
    132     }
    133     return 0;
    134 }
     1 //记忆化搜索法
     2 #include<iostream>
     3 #include<string>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<cstring>
     7 #include<algorithm>
     8 #include<vector>
     9 #include<iomanip>
    10 #include<queue>
    11 #include<stack>
    12 using namespace std;
    13 long long n;
    14 int t;
    15 long long dp[40][3];
    16 int c[40];
    17 long long dfs(int lne,int have,int lim)
    18 {
    19     if(lne<=0)
    20     return have==2;
    21     if(!lim&&dp[lne][have]!=-1)
    22     return dp[lne][have];
    23     long long ans=0;
    24     int nnum=lim?c[lne]:9;
    25     for(int i=0;i<=nnum;i++)
    26     {
    27         int nhave=have;
    28         if(have==0&&i==4) nhave=1;
    29         if(have==1&&i!=4&&i!=9) nhave=0;
    30         if(have==1&&i==9) nhave=2;
    31         ans+=dfs(lne-1,nhave,lim&&i==nnum);
    32     }
    33     if(!lim)
    34     dp[lne][have]=ans;
    35     return ans;
    36 }
    37 int main()
    38 {
    39         scanf("%d",&t);
    40         while(t--)
    41         {
    42             scanf("%lld",&n);
    43             memset(dp,-1,sizeof(dp));
    44             int cnt=0;
    45             while(n)
    46             {
    47                 c[++cnt]=n%10;
    48                 n/=10;
    49             }
    50             c[cnt+1]=0;
    51             printf("%lld
    ",dfs(cnt,0,1));
    52         }
    53     return 0;
    54 }
  • 相关阅读:
    structs2---OGNL表达式
    六种获取配置properties文件的方法
    java poi导出Excel 总结
    Linux中发布项目的一些命令笔记
    JavaScript 闭包
    常见数据库连接方式
    Docker(五):镜像
    Docker(四):docker的安装
    Ubuntu命令
    Docker(三):Docker的基本概念
  • 原文地址:https://www.cnblogs.com/--ZHIYUAN/p/5751901.html
Copyright © 2020-2023  润新知