[HDU]2089不要62

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

这道题跟Bomb(http://www.cnblogs.com/sjy123/p/3247731.html)基本一样,不过多了一个不要包含4的条件,因为数值的范围不大,本来这道题完全可以暴力完成的,不过既然刚学了数位DP,就用一用吧。

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

状态转移方程

dp[i][0]=dp[i-1][0]*9-dp[i-1][1];                            //不含62和4
dp[i][1]=dp[i-1][0];                                               //不含62和4,但2结尾
dp[i][2]=dp[i-1][2]*10+dp[i-1][1]+dp[i-1][0];         //含62和4

不解释了,得出的过程了Bomb基本一样

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

#include"stdio.h"
#include"stdlib.h"
#include"string.h"
int dp[20][3];
int a[20];
int fun(int len)
{
        
          int i,flag=0,sum=0,last=0;   //last表示一轮的位,即这轮的高一位 
          for(i=len;i>=1;i--)
          {               
               sum+=dp[i-1][2]*a[i];        
               if(flag)                   
                 sum+=dp[i-1][0]*a[i]; 
               if(!flag&&a[i]>6)           //本轮最高位大于6,需要加上低一位以2开头的数 
                 sum+=dp[i-1][1];
               if(!flag&&last==6&&a[i]>2)  //上一轮最高位等于6,要加上这轮的以2开头的个数 
                 sum+=dp[i][1];
               if(!flag&&a[i]>4)            //本轮最高位大于4,所以上一轮不含的数,这轮加上去 
                 sum+=dp[i-1][0];
               if((last==6&&a[i]==2)||a[i]==4)
                 flag=1; 
               last=a[i];      
          }
          return sum;
}
int main() 
{
     int i,len,n,m,sum1,sum2,sum,t;
     memset(dp,0,sizeof(dp));                      //初始化 
     dp[0][0]=1;
     for(i=1;i<21;i++)                            //算出彼此关系,下面计算时,直接调用 
     {     
          dp[i][0]=dp[i-1][0]*9-dp[i-1][1];                 //不含62和4 
          dp[i][1]=dp[i-1][0];                              //不含62和4,但2结尾 
          dp[i][2]=dp[i-1][2]*10+dp[i-1][1]+dp[i-1][0];     //含62和4 
     }
     while(scanf("%d%d",&n,&m)!=EOF)
     {
          if(n==0&&m==0)  break;         
          sum1=0;
          t=m-n+1;                         //n到m区间的总个数 
          len=0;           
          memset(a,0,sizeof(a));
          while(n)
          {
              a[++len]=n%10;
              n=n/10;
          }
          a[len+1]=0;
          sum1=fun(len);
          
          sum2=0;
          len=0;           
          memset(a,0,sizeof(a));
          m++;
          while(m)
          {
              a[++len]=m%10;
              m=m/10;
          }
          a[len+1]=0;
          sum2=fun(len);
          printf("%d
",t-(sum2-sum1));
     }
    // system("pause");
}

这面是暴力的作法,百度的。

#include<iostream>
#include<stdio.h> 
using namespace std;  
int a[1000001]; 
int main()
{  
    int n,m;   
    a[0]=1;  
    int i; 
    for(i=1;i<=1000000;i++) 
    {      
           if(i%10!=4&&i%100!=62&&a[i/10]==1)      
           a[i]=1;      
           else a[i]=0;  
    }  
    while(cin>>n>>m,n||m)
    {      int count=0;     
           for(int i=n;i<=m;i++)      
           {          
                if(a[i]==1) 
                count++;      
           }     
           cout<<count<<endl;  
    } 
}
View Code
原文地址:https://www.cnblogs.com/sjy123/p/3248217.html