数位dp( tzoj6061:Bomb-求49个数;tzoj1427: 不要62)

6061:http://www.tzcoder.cn/acmhome/problemdetail.do?method=showdetail&id=6061

dfs记忆化搜索

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll digit[20];
ll dp[20][2];
ll dfs(int len,bool if4,bool limit)//当前数是否是4  是否达到上界
{
    if(len==0)return 1;//搜索到最低位 最低位一定满足条件 返回1
    if(!limit&&dp[len][if4])return dp[len][if4];//未到达上界  并且这个状态已经有答案
    ll cnt=0,up_bound=(limit?digit[len]:9);  //是不是上界//n=512-> up=5
    for(ll i=0;i<=up_bound;i++){
        if(if4&&i==9)continue;//剪掉49这一支
        cnt+=dfs(len-1,i==4,limit&&i==up_bound);  //加上剩余满足条件的
    }
    if(!limit)dp[len][if4]=cnt; //不是上界;记录答案;  是上界的话答案就不能利用之前的了 要另外算
    return cnt;
}
ll solve (ll num)
{
    ll k=0;//记录几个数位
    while(num){
        digit[++k]=num%10;
        num/=10;
    }

    return dfs(k,false,true);
}
int main()
{
    ll t;
    ll n;
    cin>>t;
    while(t--){
        cin>>n;
        cout<<n-solve(n)+1<<endl;//总的减去 不包含49的(其中包括了0 所以多减了一个,要加回去)
    }
    return 0;
}
View Code

 

 

1427:http://www.tzcoder.cn/acmhome/problemdetail.do?method=showdetail&id=1427

和上一题一样;就是49改成62;再加一个4的条件即可

#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll digit[20];
ll dp[20][2];
ll dfs(int len,bool if6,bool limit)
{
    if(len==0)return 1;
    if(!limit&&dp[len][if6])return dp[len][if6];
    ll cnt=0,up_bound=(limit?digit[len]:9);
    for(ll i=0;i<=up_bound;i++){
        if(if6&&i==2)continue;
        if(i==4)continue;
        cnt+=dfs(len-1,i==6,limit&&i==up_bound);
    }
    if(!limit)dp[len][if6]=cnt;
    return cnt;
}
ll solve (ll num)
{
    ll k=0;//记录几个数位
    while(num){
        digit[++k]=num%10;
        num/=10;
    }

    return dfs(k,false,true);
}
int main()
{
    ll n,m;
    while(scanf("%I64d%I64d",&n,&m),n!=0||m!=0){
        printf("%I64d\n",solve(m)-solve(n-1));
    }
    return 0;
}
View Code

 

posted @ 2020-07-13 16:04  -第4题-  阅读(231)  评论(0编辑  收藏  举报