zoukankan      html  css  js  c++  java
  • bzoj4521

    数位dp

    复习数位dp

    数位dp一般用记忆化搜索来解决

    观察需要满足的条件,然后计入状态

    状态还要记录是否达到上线,以及前导零

    比如说这道题

    dfs(bit,a4,a8,cnt,last,limit)

    由于这道题枚举的时候不可能有前导零,所以就不记录前导零

    bit表示当前考虑第bit位,从高到低

    a4表示是否有4

    a8表示是否有8

    cnt记录最多连续出现次数,最大为3,limit记录是否卡上界

    枚举这位选什么,如果卡上界,那么从0->st[bit],否则从0->9

    然后判断状态是否更改

    如果不卡上界记忆化

    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    ll l, r;
    int top;
    int st[30];
    ll dp[12][2][2][4];
    ll dfs(int bit, int a4, int a8, int cnt, int last, int limit)
    {
        if((a4 & a8)) return 0;
        if(bit == 0) return cnt == 3;
        if(!limit && dp[bit][a4][a8][cnt] != -1) return dp[bit][a4][a8][cnt];
        ll ret = 0;
        int lim = limit ? st[bit] : 9;
        for(int i = bit == top ? 1 : 0; i <= lim; ++i) 
        {
            if(cnt == 3) ret += dfs(bit - 1, a4 || i == 4, a8 || i == 8, 3, i, limit && i == st[bit]);
            else ret += dfs(bit - 1, a4 || i == 4, a8 || i == 8, i == last ? cnt + 1 : 1, i, limit && i == st[bit]);
        }
        return limit ? ret : dp[bit][a4][a8][cnt] = ret;
    }
    ll solve(ll n) 
    {
        if(n == 1e10 - 1) return 0;
        top = 0;
        while(n)
        {
            st[++top] = n % 10;
            n /= 10;
        }
        return dfs(top, 0, 0, 0, -1, 1);
    }
    int main()
    {
        memset(dp, -1, sizeof(dp));
        scanf("%lld%lld", &l, &r);
        printf("%lld
    ", solve(r) - solve(l - 1));
        return 0;
    }
    View Code
  • 相关阅读:
    JWT
    JS中try catch的用法
    React高级
    React基础
    获取当前时间前面的时间
    nodeJs
    数组里的字符串数字与数字互转
    寒假学习(二)spark学习
    寒假学习(一)Web开发人员学习路线图
    如何使用GitHub上传本地项目(idea功能强大可直接提交)
  • 原文地址:https://www.cnblogs.com/19992147orz/p/8269899.html
Copyright © 2011-2022 走看看