• 数位DP整理总结


     数位动态规划是求解一个大区间[L, R]中间满足条件Q的所有数字的个数(或者和,或其他)的一种方法。它通过分析每一位上的数字,一般用 dp[len][digit][...] 来表示状态“len位长的数字,最高位数字为digit所具有的xx特性”,利用记忆化搜索保存中间结果,从而加快求解速度。 

    通过求 f(n) 从0到n中满足条件Q的数字的个数,则所求的结果为 f(R) - f(L-1). 

    参考于:here

    大多数数位dp都可以用一个DFS函数来进行记忆化搜索:

    #include <bits/stdc++.h>
    using namespace std;
    #define BITNUM 10
    #define MAXN 10
    int dp[BITNUM][MAXN];
    int bits[BITNUM];
    
    ///pos为当前位,digit标记状态的值(注意压缩抽象),limit 表示digit是否是第len位(从低位向高位数,个位为第1位)的范围边界
    int dfs(int pos, int digit, bool end_flag)
    {
        if(!end_flag  && dp[pos][digit] != -1)///记忆化搜索,如果之前已经求出来了,则返回。注意这里要求 end_flag为false
            return dp[pos][digit];
        if(pos==0) return dp[pos][digit]=1;
    
        int end = end_flag ? bits[pos-1] : 9 ;///如果当前位是边界数字N对应位的最大值,则下一位的范围只能从0到边界数字N的下一位的最大值。否则为0 到 9
        int ans = 0;
        for(int i = 0; i <= end; i++)
        {
            if(!(digit==6&&i==2) && i!=4)
                ans += dfs(pos - 1, i, end_flag && (i==end));
        }
    
        if (!end_flag) ///digit不是第len位的最高范围,则可以将结果缓存
            dp[pos][digit] = ans;
        return ans;
    }
    
    
    int solve(int  x)
    {
        memset(bits,0,sizeof bits);
        int pos=0;
        while(x)
        {
            bits[pos++]=x%10;
            x/=10;
        }
        return dfs(pos, bits[pos], 1);///为方便当前为设置为0
    }
    
    int main()
    {
        memset(dp,-1,sizeof dp);
        int m,n;
        while(~scanf("%d%d",&m,&n)&&(m||n))
        {
           int x1=solve(m-1);
           int x2=solve(n);
            printf("%d
    ",x2-x1);
        }
        return 0;
    }
    


    
    
    
       
    
  • 相关阅读:
    周末总结
    大数据开源框架技术汇总
    oracle迁移mysql总结
    梯度下降
    BFC的概念
    元素类型
    window10安装tensorflow
    学习使用git
    设计模式中的关系
    拟合圆
  • 原文地址:https://www.cnblogs.com/zswbky/p/6792876.html
Copyright © 2020-2023  润新知