zoukankan      html  css  js  c++  java
  • [HDU]3555Bomb

    http://acm.hdu.edu.cn/showproblem.php?pid=3555

    第一次做位数DP,卧槽,看了别人一晚上的代码,又调了一早上才做出来,艹艹艹!

    这道题讲的是,给定任意n,计算从1~n中有多少数包含连续的49.

    --------------------------------------分割线-----------------------------------------------------------

    这些是状态转移方程

    dp[i][0]=dp[i-1][0]*10-dp[i-1][1];                         //代表不含49 (当位数增加一位,不含49的数增加10倍,但是要减去一个以9开头的)
    dp[i][1]=dp[i-1][0];                                             //代表不含49,但以9开头(当位数增加一位,就增长了在原来不以9开头的那些)
    dp[i][2]=dp[i-1][2]*10+dp[i-1][1];                       //代表包含49(当位数增加一位,之前已经包含49的增加10倍,另外要加上现在开头为4和之前开头为9组合成49的数)

    当然状态转移方程不止这一种,如:

    dp[k][0]=dp[k-1][0]*9+dp[k-1][1]*8;                   //dp[][0]表示不包含49并且以非4结尾的个数

    dp[k][1]=dp[k-1][0]+dp[k-1][1];                          //dp[][1]表示不包含49并且以4结尾的个数

    dp[k][2]=dp[k-1][1]+dp[k-1][2]*10;                     //dp[][2]表示包含49的个数

    --------------------------------------分割线-----------------------------------------------------------

    另外,此题N (1 <= N <= 2^63-1),所以要输入的话要用字符型(即字符串输入),或定义成long long

    #include"stdio.h"
    #include"stdlib.h"
    #include"string.h"
    long long dp[20][3];
    int main() 
    {
         int t,len,i,j,a[20],flag,last;
         long long n,sum;
         memset(dp,0,sizeof(dp));                      //初始化 
         dp[0][0]=1;
         for(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]; 
         }
         scanf("%d",&t);
         while(t--)
         {
              scanf("%I64d",&n);               
              n++;                   //处理末尾2位是49的特殊情况 
              len=0;
              memset(a,0,sizeof(a));
              while(n)
              {
                  a[++len]=n%10;
                  n=n/10;
              } 
              flag=0;
              sum=0;
              last=0;
              for(i=len;i>=1;i--)
              {               
                   sum+=dp[i-1][2]*a[i]; 
                   if(flag)                  //如果其高位存在49,则低位不管是什么数都存在 
                   sum+=dp[i-1][0]*a[i];
                   if(!flag&&a[i]>4)           //2位置,且首位大于等于5,至少存在低一位有9的情况的个数 
                   sum+=dp[i-1][1];
                   if(last==4&&a[i]==9)
                   flag=1; 
                   last=a[i];      
              }
              printf("%I64d
    ",sum);
         }
        // system("pause");
    }
  • 相关阅读:
    SEH(Structured Exception Handling)详细解释
    Command Query Responsibility Segregation
    C#中Func和Expression的区别
    C#的yield return是怎么被调用到的?
    C#的static constructor抛了异常会怎么处理?
    developer应该知道的image知识(JPG和PNG)
    网站前台与后台的连接
    短消息类新旧服务代码对应表
    无线广告巨头渠道火拼
    中国移动下一代移动技术将选择LTE
  • 原文地址:https://www.cnblogs.com/sjy123/p/3247731.html
Copyright © 2011-2022 走看看