zoukankan      html  css  js  c++  java
  • hdoj4734(数位dp优化)

    题目链接:https://vjudge.net/problem/HDU-4734

    题意:定义一个十进制数AnAn-1...A1的value为An*2n-1+...+A1*20,T组样例(<=1e4),每组样例给出a、b,求出[0,b]中value小于等于a的value的数的个数。

    思路:数位dp,第一能想到将Ai*2i-1的和作为状态,即dp[len][sum]表示到长度为len的数中value为sum的数的个数,最后判断sum<=value(a)来确定是否满足条件。但是问题来了,我们会发现这样的状态与输入a相关,而输入有1e4组,时间限制为500ms,每次还都要memset(dp),显然会超时。

      这个时候就要优化,利用减法,dp[len][sum]表示长度len中value<=sum的数的个数,这一状态性质是所有数共有的性质,与输入a无关,因此可以保存dp的值,而不用memset,最后的结果就是递归到最后一层的sum>=0的数的个数,即value<=value(a)。

    AC代码:

    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int a[10],dp[10][4700],T;
    
    int gets(int x){
        int k=0,ret=0;
        while(x){
            ret+=(1<<k)*(x%10);
            x/=10;
            k++;
        }
        return ret;
    }
    
    int dfs(int pos,int sum,bool limit){
        if(pos==-1) return 1;
        if(!limit&&dp[pos][sum]!=-1) return dp[pos][sum];
        int up=limit?a[pos]:9;
        int tmp=0;
        for(int i=0;i<=up;++i){
            int t=sum-(1<<pos)*i;
            if(t<0) continue;
            tmp+=dfs(pos-1,t,limit&&i==a[pos]);
        }
        if(!limit) dp[pos][sum]=tmp;
        return tmp;
    }
    
    int solve(int x,int sum){
        int pos=0;
        while(x){
            a[pos++]=x%10;
            x/=10;
        }
        return dfs(pos-1,sum,true);
    }
    
    int main(){
        memset(dp,-1,sizeof(dp));
        scanf("%d",&T);
        for(int i=1;i<=T;++i){
            int a,b,suma;
            scanf("%d%d",&a,&b);
            suma=gets(a);
            printf("Case #%d: %d
    ",i,solve(b,suma));
        }
        return 0;
    }
  • 相关阅读:
    [转][html5]网页横屏
    [转][EasyUI]扩展 DateBox
    [转][C#]枚举的遍历Enum
    [转][C#]单例模式之懒加载
    [C#][Quartz]添加监听器
    [C#][Quartz]帮助类
    [转]Win 10 的 Win 按键没反应
    转来的--轻松自动化---selenium-webdriver(python) (七)---定位iframe——转来的
    安装charles
    遇到的问题汇总
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/10753118.html
Copyright © 2011-2022 走看看