zoukankan      html  css  js  c++  java
  • HDU 4734 F(x) 数位DP

    数位DP 越来越顺了。但是无脑了一下,对于每组数据都删除记忆,10000组数据档当然TLE了。

    题意:求0~b中有多少个数X, 其f(x)<=f(a)

    分析:

    设g[i][j]表示长度为i的数,距离f(a)还剩j的量。

    g[i][j]=Σ(g[i-1][j-k*2^(i-1)]  (0<=k<=9)

    然后就是套路了。

    #include <stdio.h>
    #include <string.h>
    int g[20][10000];
    int f(int x)
    {
        int sum=0;
        int y=1;
        while (x>0)
        {
            sum+=y*(x%10);
            x/=10;
            y=y*2;
        }
        return sum;
    }
    int dp(int i,int j)
    {
        if (j<0)
        {
            return 0;
        }
        if (g[i][j]!=-1)
        {
            return g[i][j];
        }
        if (i==0)
        {
            if (j<0)
            {
                return 0;
            }
            else
            {
                return g[i][j]=1;
            }
        }
        int ans=0;
        for (int k=0;k<=9;k++)
        {
            if ((j-k*(1<<(i-1)))>=0)
                ans+=dp(i-1,j-k*(1<<(i-1)));
        }
        return g[i][j]=ans;
    }
    int main()
    {
        int i,j,k;
        int t;
        int len;
        int a,b;
        int last;
        int digit[100];
        int cas=0;
        scanf("%d",&t);
        memset(g,-1,sizeof(g));
        while (t--)
        {
    
            scanf("%d%d",&a,&b);
            last=f(a);
            len=0;
            b++;
            while (b>0)
            {
                digit[++len]=b%10;
                b/=10;
            }
            int ans=0;
            for (i=len;i>=1;i--)
            {
                for (j=0;j<digit[i];j++)
                {
                    ans+=dp(i-1,last-j*(1<<(i-1)));
                }
                last-=digit[i]*(1<<(i-1));
            }
            printf("Case #%d: %d
    ",++cas,ans);
        }
        return 0;
    }

    这里有个浓缩版。 from  CXL。

    #include <cstdio>
    #include <cstring>
    
    int dp[12][10000];
    int num[30];
    
    int getf(int x) {
        int ans = 0;
        int len = 0;
        while (x) {
            ans += (x%10)*(1<<(len));
            x/=10;
            len++;
        }
        return ans;
    }
    
    int dfs(int i, int f, bool isQuery) {
        if (f < 0) return 0;
        int &nowdp = dp[i][f];
        if (!isQuery && ~nowdp) return nowdp;
        if (i == 0) {
            return 1;
        }
        int end = isQuery?num[i]:9; /*这里不一样哦!*/
        int ans = 0;
        for (int j = 0; j <= end; j++) {
            int nextf = f-j*(1<<(i-1)); /*这里不一样哦!*/
            ans += dfs(i-1, nextf, isQuery && j==end);
        }
        if (!isQuery) nowdp = ans;
        return ans;
    }
    
    int cal(int a, int x) {
        int len = 0;
        if (x == 0) {
            num[++len] = 0;
        } else {
            while (x) {
                num[++len] = x%10;
                x/=10;
            }
        }
        return dfs(len, getf(a), true); /*这里不一样哦!*/
    }
    
    int main() {
        int t;
        scanf("%d", &t);
        memset(dp, -1, sizeof(dp));
        int cas = 1;
        while (t--) {
            printf("Case #%d: ", cas++);
            int a, b;
            scanf("%d%d", &a, &b);
            printf("%d
    ", cal(a,b));
        }
        return 0;
    }
  • 相关阅读:
    跟我学android—01.SplashActivity
    eclipse android : A project with that name already exists in the workspace
    冬吴相对论锦言佳句--0005.薄伽梵歌与“印度式管理”
    [转载]Jquery Form插件表单参数
    Form表单学习网站
    [转载]JQuery获取元素文档大小、偏移和位置和滚动条位置的方法集合
    jquery捕捉文本域输入事件
    [转载]js 遍历数组对象
    C#跳出循环的几种方法的区别
    [转载]MVC3缓存:使用页面缓存
  • 原文地址:https://www.cnblogs.com/six-god/p/3601018.html
Copyright © 2011-2022 走看看