• 数位dp


    问题:在一个给定的区间[a,b]内,找满足要求的数。

    如果我们用暴力的话一般要考虑数的大小,而数位dp要考虑的确实数的组成。

    例如:  递增的  1234  1357  2468

              整除13的  13 26 39

              包含13的  132 2134

              双峰的   152630  243052

    如果数的位数大于100,暴力肯定Over。

    数位dp要注意的就是数的组成处理以及数的边界处理。

    核心思路:记忆化搜索+记录合适状态。数位dp顾名思义就是逐位dp逐位考虑。

    举例: [0,8457]内逐位递增的数有多少个。那么我们先对第一位进行处理,即枚举0XXX,1XXX,...8XXX。当我们枚举到第二位的时候。05XX,15XX,25XX...75XX,后面两位XX前的状态量都是5,如果我们已经处理了05XX后面满足要求的数的个数,那么我们15XX,25XX...是不是也可以利用那个已经求得的结果呢,利用深搜的那个结果可以用记忆化搜索预先求得。

    开辟空间dp[len][state],表示最后len位前面状态为state时满足要求的数的个数。

    hdu2089 

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089

    题目大意:求区间[a,b]内不含4和62的数有多少个。

    思路: dp[len][state],state表示后面len位数之前一位那个数是否为6,是则为1不是则为0

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 
     7 int dp[8][2];
     8 int digit[10];
     9 
    10 int dfs(int len, int state, int fp)
    11 {
    12       if(!len) return 1;
    13       if(!fp&&dp[len][state]!=-1) return dp[len][state];
    14       int ret=0, fpmax=fp?digit[len]:9;
    15       for(int i=0; i<=fpmax; i++)
    16       {
    17           if(i==4||(state&&i==2)) continue;
    18           ret+=dfs(len-1,i==6,fp&&i==fpmax);
    19       }
    20       if(!fp) dp[len][state]=ret;
    21       return ret;
    22 }
    23 
    24 int cal(int n)
    25 {
    26     int len=0;
    27     memset(dp,-1,sizeof(dp));
    28     while(n)
    29     {
    30         digit[++len]=n%10;
    31         n/=10;
    32     }
    33     return dfs(len,false,true);
    34 }
    35 
    36 int main()
    37 {
    38     int a, b;
    39     while(scanf("%d%d",&a,&b),a+b)
    40     {
    41         printf("%d
    ",cal(b)-cal(a-1));
    42     }
    43     return 0;
    44 }
    View Code

    hdu3652 

    题目大意:求区间[a,b]内包含子串13以及是13的倍数的数有多少个。

    思路:dp[len][pre][state],state表示后面len位数之前一位那个数是否为1,是则为1不是则为0,如果已经出现13则为2,pre记录前面各位数的余数。

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3652

  • 相关阅读:
    MFC下拉框使用方法
    C++学习之路,漫长而遥远
    [转载]浅析STL allocator
    [转载]《STL源码剖析》阅读笔记之 迭代器及traits编程技法
    回溯算法之n皇后问题
    算法练习之一
    Windows配置JDK and TOMCAT
    搭建openstack allinone版本
    在ms08_067_netapi中添加2003的Chinese版本
    msfvenom各平台木马生成
  • 原文地址:https://www.cnblogs.com/kane0526/p/3546513.html
Copyright © 2020-2023  润新知