• 【算法笔记】数位dp


    ·前言

    当我们遇到某些题目的时候(比如像让你统计l——r这一个区间内的数字和以及满足条件的数有几个这一类的题目),常常会因为区间太大而无法计算。这时候,我们就需要用上我们伟大的数位dp啦!

    数位dp的实质就是换一种暴力枚举的方式,使得新的枚举方式满足dp的性质,然后记忆化就可以了。(nm这本质上不还是记忆化搜索)

    (PS:虽然说数位dp是可以用正常的递推算法来写的,但是递推不仅难想还难调的一批,没准就一不小心人就没了,还是用记忆化搜索板子攻克这一切吧)

    (PPS:记忆化搜索背个板子就好,但是特别难查错qwq)

    ·基本思维

    由于递推版的数位dp本质上就是个找规律枚举状态的过程,其实和记忆化搜索差不了多少(而且我不会写QAQ)。所以该篇博就讲记忆化搜索的方法就over了……

    考虑一下枚举每一位(pos)的数字(记得确定一下上界(limit)qwq),以及在中途判断是否存在有前导零(lead),接下来就可以愉快地记忆化搜索啦~

    state状态需要根据题目的不同而确定哦qwq

    给个板子趴(

    #include<bits/stdc++.h>
    using namespace std;
    int a[20];
    long long dp[20][state];
    long long dfs(int pos,int state,bool lead,bool limit){
        if(!pos)return 1;
        if(!limit&&!lead&&dp[pos][state]!=-1)return dp[pos][state];
        int up=limit?a[pos]:9;
        long long ans=0;
        for(int i=0;i<=up;i++){
            if() ...
            else if()...
            ans+=dfs(pos-1, ,lead&&i==0,limit&&i==a[pos])
        }
        if(!limit&&!lead)dp[pos][state]=ans;
        return ans;
    }
    long long solve(long long x){
        int pos=0;
        while(x){
            a[++pos]=x%10;
            x/=10;
        }
        return dfs(pos,1,1);
    }
    int main(){
        long long l,r;
        while(~scanf("%lld%lld",&l,&r))
            printf("%lld
    ",solve(r)-solve(l-1));
    }
    View Code

    ·题目汇总

    HDU3652 B-Number
    01 Luogu4317/BZOJ3209 
    02 BZOJ 1833 ZJOI2010 Count
    03 HDU4734 f(x)
    04 Codeforces 55D Beautiful Number
    05 2012 Multi-University Training Contest 6 XHXJ’s LIS
    06 HDU4507 
    *依旧莫得链接,以后把题解整出来再说吧qwq
  • 相关阅读:
    三种方法使HTML单页面输入密码才能访问
    JAVA知识汇总
    session 一致性的解决方案
    Debian 9 Stretch国内常用镜像源
    Java开发工具推荐
    Centos配置vsftpd
    [转]php实时输出内容
    php javascript comet
    使用安装 php-memcache-client
    [转]网页实时聊天之js和jQuery实现ajax长轮询 PHP
  • 原文地址:https://www.cnblogs.com/linskyQWQ/p/13476311.html
Copyright © 2020-2023  润新知