hdu3555Bomb 数位dp

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std ;
const int maxn = 20 ;
int bit[maxn] ;
__int64 dp[maxn][maxn][2] ;//dp[i][j][1]第i位数为j时内有49的数量,0位不含
void init()
{
    memset(dp , 0 ,sizeof(dp)) ;
    for(int i = 0;i <= 9;i++)
    dp[1][i][0] = 1,dp[1][i][1] = 0;
    for(int i = 2;i < maxn ;i++)
      for(int j = 0;j <= 9;j ++)
        for(int k = 0;k <= 9 ;k++)
        {
            if(j == 4 && k == 9)
            dp[i][j][1] += (dp[i-1][k][1] + dp[i-1][k][0]) ;
            else
            {
                dp[i][j][1] += dp[i-1][k][1] ;
                dp[i][j][0] += dp[i-1][k][0] ;
            }
        }
}
__int64 solve(int len)
{
    __int64 ans = 0 ;
    int flag = 0;
    for(int i = len;i > 0 ;i--)
    {
       for(int j = 0;j <  (i == 1 ? (bit[i]+1) : bit[i]) ;j++)
       ans+=dp[i][j][1] ;
       if(flag == 2)
       for(int j = 0;j < (i == 1 ? (bit[i] + 1): bit[i] );j++)
       ans+=dp[i][j][0];
       if(flag == 1 && i == 1 && bit[1] ==9 )
       ans++ ;
       if(flag == 1 && bit[i] == 9)
       flag = 2;
       else if(bit[i] == 4 && flag == 0)
       flag = 1;
       else if(flag == 1 && bit[i] !=4)
       flag = 0;
    }
    return ans ;
}
int main()
{
   // freopen("input.txt","r",stdin) ;
    int T ;
    scanf("%d" ,&T) ;
    __int64 n;
    while(T--)
    {
        scanf("%I64d" ,&n) ;
        __int64 t = n;
        int len = 0;
        while(t)
        {
            bit[++len] = t%10 ;
            t/=10 ;
        }
        init() ;
        printf("%I64d\n" ,solve(len)) ;
    }
    return 0;
}































你可能感兴趣的:(hdu3555Bomb 数位dp)