• LightOJ 1140: How Many Zeroes? (数位DP)


    当前数位DP还不理解的点:

    1:出口用i==0的方式

    2:如何省略状态d(就是枚举下一个数的那个状态。当然枚举还是要的,怎么把空间省了)

     

    总结:

    1:此类DP,考虑转移的时候,应当同时考虑查询时候的情况。

    2:考虑x在第i位之后,能遍历多少数字,其答案为(x%10i-1+1)

    3:这里的记忆化搜索不太一样喔,出口一定要写在递归里,不然,查询状态下差到出口就会出错了~

     

    类型:

    数位DP

    题意:

    求[A,B]区间内的所有数,写下来之后,0的个数。(a,b 为 unsigned int)

    思路:

    我的笨拙暴力状态:

    dp[i][d][okPre] 表示d开头的i位数,(okPre表示计算前导0的情况下,反之~),的0的个数。

    那么。

    dp[i][d][含] = dp[i-1][0~9(num[i-1])][含] + 10i-1(x%10i-1+1) * (d==0);

    dp[i][d][不含] = dp[i-1][1~9(num[i-1])][含] + dp[i-1][0][d==0?不含:含] ;

    出口:

    dp[1][1~9][含] =dp[1][1~9][不含] = 0;

    dp[1][0][不含] = dp[1][0][含] = 1;

    当时确定出口的时候,不含的0应该是0还是1呢?不好确定,感觉是1,最后是通过试验确定的。

    还是没有理解别人代码中 用 i==0 做出口 是怎么实现的。


    我的代码:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    long long nowx;
    long long dp[20][10][2];
    int num[30];
    
    
    long long dfs(int i, int d, bool okPreZero, bool isQuery) {
        //printf("(%d,%d,%s,%s)
    ", i, d, okPreZero?"T":"F", isQuery?"T":"F");
        long long &nowdp = dp[i][d][okPreZero];
        if (!isQuery && ~nowdp) return nowdp;
        if (i == 1) {
            if (d!=0) return nowdp = 0;
            else if (okPreZero) {
                return nowdp = 1;
            } else {
                return nowdp = 1;
            }
        }
        long long ans = 0;
        int end = isQuery?num[i-1]:9;
        for (int j = 0; j <= end; j++) {
            if (okPreZero) {
                ans += dfs(i-1,j,true,isQuery && j==end);
            } else {
                if (d == 0 && j == 0) {
                    ans += dfs(i-1,j,false,isQuery && j==end);
                } else {
                    ans += dfs(i-1, j, true, isQuery && j==end);
                }
            }
        }
        long long ten = 1;
        for (int j = 0; j < i-1; j++) ten*=10;
        if (d==0 && okPreZero) ans += (isQuery?((nowx%ten)+1):(ten));
        if (!isQuery) nowdp = ans;
        return ans;
    }
    
    long long cal(long long x) {
        nowx = x;
        if (x == -1) return 0;
        if (x == 0) return 1;
        int len = 0;
        while (x) {
            num[++len] = x%10;
            x/=10;
        }
        return dfs(len+1, 0, false, true);
    }
    
    
    int Nmain() {
        long long a;
        memset(dp, -1, sizeof(dp));
        while (cin>>a) {
            cout<<"---"<<cal(a)<<endl;
        }
        return 0;
    }
    
    int main() {
        int t;
        cin>>t;
        int cas = 1;
        memset(dp, -1, sizeof(dp));
        while (t--) {
            long long m, n;
            cin>>m>>n;
            cout<<"Case "<<cas++<<": "<<cal(n)-cal(m-1)<<endl;
        }
        return 0;
    }

    不理解的代码:

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    typedef long long LL;
    LL dp[14][12][2];
    int bit[14],len;
    LL a,b;
    LL dfs(int pos,int v,int flag,int limit)
    {
        if (pos<=0) return flag?v:0;
        if (!limit&&dp[pos][v][flag]!=-1) return dp[pos][v][flag];
        int end=(limit?bit[pos]:9);
        LL re=0;
        for (int i=0;i<=end;i++)
            {
                int tmp;
                if (flag&&(i==0)) tmp=1;else tmp=0;
                re+=dfs(pos-1,v+tmp,flag||i,limit&&(end==i));
            }
        if (!limit) dp[pos][v][flag]=re;
        return re;
    }
    
    LL solve(LL n)
    {   if (n==-1) return -1;
        if (n==0) return 0;
        len=0;
        while (n)
            {   bit[++len]=n%10;
                n/=10;
            }
        return dfs(len,0,0,1);
    }
    int main()
    {   memset(dp,255,sizeof(dp));
        int cas,i=0;
        scanf("%d",&cas);
        while (cas--)
            {scanf("%lld%lld",&a,&b);
             printf("Case %d: %lld
    ",++i,solve(b)-solve(a-1));
            }
        return 0;
    }
  • 相关阅读:
    .NET的委托和匿名函数应用一例
    C#中,变量前的@符号
    ExtJs中多个form情况下指定某个form使能
    【Python web 开发】个人中心-用户收藏功能
    【Python web 开发】用户个人信息修改
    【Python web 开发】django rest framwork 动态设置serializers
    【Python web 开发】django rest framwork动态设置权限premission
    【fiddler】用fiddler 拦截请求修改response 回包测试
    【Python web 开发】联合唯一索引
    【Python web 开发】用户收藏功能
  • 原文地址:https://www.cnblogs.com/shinecheng/p/3599416.html
Copyright © 2020-2023  润新知