• 数位dp模版(dp)


     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 
     8 int t;
     9 long long dp[19][19][2005];
    10 long long l, r;
    11 int shu[20];
    12 
    13 long long dfs(int len,..., bool shangxian)
    14 {
    15     if (len == 0)
    16         return ...;
    17     if (!shangxian && dp[len][...])
    18         return dp[len][...];  //dp数组的内容应和dfs调用参数的内容相同,除了是否达到上限
    19     long long cnt = 0;
    20     int maxx = (shangxian ? shu[len] : 9);
    21     for (int i = 0; i <= maxx; i++)
    22     {
    23         ...;
    24         cnt += dfs(len - 1,..., shangxian && i == maxx);
    25     }
    26     if (!shangxian)
    27         dp[len][...] = cnt;
    28     return cnt;
    29 }
    30 
    31 long long solve(long long x)
    32 {
    33     int k = 0;
    34     while (x)
    35     {
    36         shu[++k] = x % 10;
    37         x /= 10;
    38     }
    39     return dfs(k,...,1)
    40 }
    41 
    42 int main()
    43 {
    44         memset(dp, 0, sizeof(dp));
    45         scanf("%lld%lld", &l, &r);   //有些题目其实并不需要用到long long
    46         printf("%lld
    ", solve(r) - solve(l - 1)); //只有满足区间减法才能用
    47 
    48     //while (1);
    49     return 0;
    50 }
    View Code

    数位dp是一种计数用的dp,一般就是统计一个区间[l,r]内满足一些条件数 的个数,所谓数位dp,字面意思就是在数位上dp。数位的含义:一个数有个位,十位,百位,千位···数的每一位就是数位。

    之所以要引入数位的概念完全就是为了dp。数位dp的实质就是换一种暴力枚举的方式,使新的枚举方式满足dp的性质,然后记忆化即可。

    两种不同的枚举:对于一个求区间[l,r]满足条件数的个数,最简单的暴力如下:

    for(int i=l;i<=r;i++)
               if(right(i))
                      ans++;
    

      然而这样枚举不方便记忆化,或者根本无状态可言。

  • 相关阅读:
    de4dot 反混淆
    GreyMagic
    HearthBuddy 第一次调试
    dnSpy
    asp.net form submit 在Chrome里面看Form提交
    关于并发模型 Actor 和 CSP
    Go语言并发机制初探
    CyclicBarrier的工作原理及其实例
    Java并发编程--CyclicBarrier
    CountDownLatch的简单理解
  • 原文地址:https://www.cnblogs.com/Roni-i/p/7307765.html
Copyright © 2020-2023  润新知