HDU 3555 Bomb(数位DP)

http://acm.hdu.edu.cn/showproblem.php?pid=3555
过年了…好懒…坎坷的回家….拜年…走亲戚…balabala…..玩了几天…然后..为了不影响进度….把插头DP跳过去了…(好懒….
第一道数位DP
感觉这个数位DP就是找到每一个数位的状态的个数,然后通过遍历这个数来找到题目需要的状态的答案
题意:给一个n,输出1~n里含有 49子序列的数的数量
思路: 最基础的数位DP,先找到每一位三种状态的数量,然后通过枚举N来找到答案

#include<map>
#include<set>
#include<queue>
#include<stack>
#include<math.h>
#include<string>
#include<vector>
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm> 
using namespace std;
typedef long long LL;
#define maxn 1005
#define f(x) (x*1.0)
#define inf 0x3f3f3f3f
#define maxm maxn*maxn
#define min(a,b) (a>b?b:a)
#define max(a,b) (a>b?a:b)
#define lowbit(x) (x&(-x))
#define cheak(i) printf("%d ",i)
#define lson(x) (splay[x].son[0])
#define rson(x) (splay[x].son[1])
#define rfor(i,a,b) for(i=a;i<=b;++i)
#define lfor(i,a,b) for(i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define mec(a,b) memcpy(a,b,sizeof(b))
LL dp[25][3];
//0 不含有49的个数 
//1 不含有49但最高位是9的个数 
//2 含有49的个数 
void init()
{
//寻找每一个状态在每一位的个数
    dp[0][0]=1;
    dp[0][1]=dp[0][2]=0;
    int i;
    rfor(i,1,25) 
    {
        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];
    }
}
LL A[25];
LL solve(LL n)
{
    int len=0,i;
    LL ans=0;
    while(n)
    {
        A[++len]=n%10;
        n/=10;
    }
    A[len+1]=0;//这一步是防止上次输入对这次造成影响
    bool flag=false; 
    lfor(i,len,1)//从高位到地位遍历 
    {
        ans+=dp[i-1][2]*A[i];
        if(flag) ans+=dp[i-1][0]*A[i];
        else if(A[i]>4) ans+=dp[i-1][1];
        if(A[i+1]==4&&A[i]==9) flag=true;
    }
    if(flag) ans++;
    return ans;
}
int main()
{
    int T;
    LL n;
    init();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld",&n);
        printf("%lld\n",solve(n));
    }
    return 0;
}

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