HDU3555Bomb(记忆化搜索)

题目与不要62相似,数位dp

#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf -0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
ll dp[25][3];
//dp[i][0] 有i位且都不含49
//dp[i][1] 有i位且第i位为9
//dp[i][2] 有i位且都含49

void init(){
    mem0(dp);
    dp[0][0]=1;
    for(int i=1;i<=22;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];
    // cout<<"PPPP"<<i<<"PPPP"<<dp[i][0]<<"PPPP"<<dp[i][1]<<"PPP"<<dp[i][2]<<endl;
    }
}

__int64     solve(__int64 n){
    int len=0,a[100];
    while(n){
        a[++len]=n%10;
        n/=10;
    }
    a[len+1]=0;
    __int64 ans=0;
    int flag=0;
// for(int i=len;i>=1;i--)
// cout<<"PPPP"<<a[i]<<endl;
    for(int i=len;i>=1;i--){
        ans+=dp[i-1][2]*a[i];
        if(flag)
            ans+=dp[i-1][0]*a[i];   //不要忘记乘以a[i]! 
        if(!flag&&a[i]>4)
            ans+=dp[i-1][1];
        if(a[i]==9&&a[i+1]==4)
            flag=1;
    }
    return ans;
}

int main(){
    init();
    int t;
    __int64 n;
    scanf("%d",&t);
    while(t--){
        scanf("%I64d",&n);
        printf("%I64d\n",solve(n+1));
    }
    return 0; 
}




#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int bit[100];
ll dp[20][3];

ll dfs(int p,int have,int lim){
    int have_x;
    if(p<=0)
        return (have==2);
    if(lim!=1&&dp[p][have]!=-1)
        return dp[p][have];
    int num= lim?bit[p]:9;              //lim为0表示下一位没有限制,lim为1表示下一位有限制
    ll ans=0;
    for(int i=0;i<=num;i++){            //have=0表示末尾既不是9也不是4
        have_x=have;                    //have=1表示末尾是4
        if(have==1&&i!=4)               //have=2表示存在4和9连在一起
            have_x=0;
        if(have==1&&i==9)
            have_x=2;
        if(have==0&&i==4)
            have_x=1;
        ans+=dfs(p-1,have_x,lim&&(num==i));
        //printf("%d %d %I64d\n",p,i,ans);
    }
    if(!lim)
        dp[p][have]=ans;
    return ans;
}

void work(ll n){
    int len=0;
    while(n){
        bit[++len]=n%10;
        n/=10;
    }
    bit[len+1]=0;
    printf("%I64d\n",dfs(len,0,1));
}

int main(){
    ll n;
    int t;
    memset(dp,-1,sizeof(dp));
    scanf("%d",&t);
    while(t--){
        scanf("%I64d",&n);
        work(n);
    }
    return 0;
}

你可能感兴趣的:(HDU3555Bomb(记忆化搜索))