HDU 3555 Bomb (数位dp)

来源:互联网 发布:无痕植发的价格 知乎 编辑:程序博客网 时间:2024/06/14 15:28

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

题意:求出1到N (1 <= N <= 2^63-1)的数中,包含“49”的数的个数。

思路:用数位dp的记忆化搜索模版。

代码:

#include <stdio.h>#include <string.h>#include <math.h>#include <algorithm>#define MOD 1000000007#define INF 0x7fffffffusing namespace std;typedef long long ll;int bit[70];ll f[70][5];ll dp(int pos, int sta, int flag){    //第len到pos+1位的数字已确定,现在要确定第pos位    //sta=0则前面确定的序列不含49,sta=1则第pos-1位为4,sta=2则前面确定的序列包含49    //flag=1,不论该位为多少都比N小    if(pos == 0) return sta == 2;    if(flag && f[pos][sta] != -1) return f[pos][sta];    int x = flag ? 9 : bit[pos];    ll ans = 0;    for(int i = 0; i <= x; i++)    {        if(sta == 2 || (sta == 1 && i == 9))        {            ans += dp(pos - 1, 2, flag || i < x);        }        else if(i == 4)        {            ans += dp(pos - 1, 1, flag || i < x);        }        else        {            ans += dp(pos - 1, 0, flag || i < x);        }    }    if(flag) f[pos][sta] = ans;    return ans;}ll cal(ll n){    int len = 0;    while(n)    {        bit[++len] = n % 10;        n /= 10;    }    ll ans = dp(len, 0, 0);    return ans;}int main(){    #ifdef LOCAL    freopen("dpdata.txt", "r", stdin);    #endif    int t;    ll n;    scanf("%d", &t);    memset(f, -1, sizeof(f));    while(t--)    {        scanf("%I64d\n", &n);        printf("%I64d\n", cal(n));    }    return 0;}



0 0