zoukankan      html  css  js  c++  java
  • 「Luogu4124」 [CQOI2016]*

    problem

    Solution

    这里我采用记忆化搜索的形式实现有哪个大佬可以教教我递推板的数位dp啊

    搜索的过程中记录是否曾出现8,是否曾出现4,是否曾有连续3个相同数字,搜到底返回就可以了

    其实没有太多好写的,数位DP很多都是套模板

    那还写来干嘛?

    这道题

    (1e10)开始算!

    (1e10)开始算!

    (1e10)开始算!

    这就意味着我们需要特殊处理最高位,而不是像普通的数位DP那样直接把最高位也丢进搜索里搜。

    惨痛的70分教训大概只有我是这么蠢了嘤嘤嘤

    Code

    #include <cstdio>
    #include <iostream>
    #include <cstdlib>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #define maxb 15
    using namespace std;
    typedef long long ll;
    
    ll l,r;
    ll dp[maxb][15][15][2][2][2];
    ll b[maxb],len;
    
    ll dfs(ll pos,ll lst,ll llst,bool rep,bool four,bool eight,bool limit)
    {
        if(!pos)
            return ((!eight)||(!four))&&rep;
        if(~dp[pos][lst][llst][rep][four][eight] && !limit)
            return dp[pos][lst][llst][rep][four][eight];
        ll re=0;
        for(register ll i=0;i<=(limit?b[pos]:9);++i)
            re+=dfs(pos-1,i,lst,rep||((i==lst)&&(lst==llst)),four||(i==4),eight||(i==8),limit&&(i>=b[pos]));
        if(!limit)
            dp[pos][lst][llst][rep][four][eight]=re;
        return re;
    }
    
    ll Work(ll num)
    {
        if(num<1e10)
            return 0;
        memset(dp,-1,sizeof(dp));
        memset(b,0,sizeof(b));
        len=0;
        while(num)
        {
            b[++len]=num%10;
            num/=10;
        }
        ll re=0;
        for(register ll i=1;i<=b[len];++i)
            re+=dfs(len-1,i,10,0,i==4,i==8,i==b[len]);
        return re;
    }
    
    int main()
    {
        scanf("%lld%lld",&l,&r);
        printf("%lld",Work(r)-Work(l-1));
        return 0;
    }
    
  • 相关阅读:
    Python爬虫重写。
    python threading
    问题8:手机端实现点击按钮时更换颜色(解决IOS不显示背景)
    问题7:JavaScript 常用正则示例
    常见问题6:控制台报错整理——报错
    常见问题5:图片与文字垂直居中
    bootstrap学习总结
    常见问题4:文本不能选择 效果
    常见问题3:自适应大小高度与宽度
    javascript——10章 DOM
  • 原文地址:https://www.cnblogs.com/lizbaka/p/10263624.html
Copyright © 2011-2022 走看看