zoukankan      html  css  js  c++  java
  • # Acwing 338 计数问题(数位dp+前导0处理)

    题意

    给定([a,b]),求区间中所有数字中0-9出现的次数。

    例如,a=1024,b=1032,则 a 和 b 之间共有9个数如下:

    1024 1025 1026 1027 1028 1029 1030 1031 1032

    其中‘0’出现10次,‘1’出现10次,‘2’出现7次,‘3’出现3次等等…

    思路

    理解了数位DP的话,这就是一道简单题了,这里主要是为处理前导0做个笔记,方便以后查阅。

    在DFS中是用lead标记是否有前导0限制,lead==1表示有前导0限制。

    前导0限制(表示最高位不能取0,例如0123,应该表示成123)向下一层传递的条件是lead==1&&i==0也就是说当前位有前导0限制,并且当前位取0的时,下一层有前导0限制。

    需要记录的是,前(i)位满足条件的数的个数(f[i].cnt),和前(i)位每个数字出现的次数。

    递推公式:

    (i)位取(j)

    f[i].cnt+=f[i-1].cnt;
    f[i].a[j]+=f[i-1].cnt;//第i位取j时,前i-1为满足条件的数个数就是第i位j出现的次数
    for(int j=0;j<=9;j++)f[i].a[j]+=f[i-1].a[j];
    

    代码

    #include <bits/stdc++.h>
    using namespace std;
    struct node{
        int cnt;
        int a[10];
        node(){
            cnt=0;
            memset(a,0,sizeof a);
        }
    }f[12];
    int a[12];
    inline node dfs(int pos,bool limit,bool lead){
        if(pos==-1){
            node tmp;
            tmp.cnt=1;
            return tmp;
        }
    
        if(!limit&&!lead&&f[pos].cnt!=-1)return f[pos];
        int up=limit?a[pos]:9;
        node res;
        for(int i=0;i<=up;i++){
            //if(lead&&i==0)continue;
            node tmp=dfs(pos-1,limit&&i==a[pos],lead&&i==0);
            res.cnt+=tmp.cnt;
    
            if(!(lead&&i==0)) res.a[i]+=tmp.cnt;
    
            for(int i=0;i<=9;i++)res.a[i]+=tmp.a[i];
        }
        return (limit||lead)?res:f[pos]=res;
    }
    inline node sol(int n){
        if(!n){
            node tmp;
            return tmp;
        }
    
        memset(f,-1,sizeof f);
        int pos=0;
        while (n)a[pos++]=n%10,n/=10;
    
        return dfs(pos-1, true,true);
    }
    int main(){
        int l,r;
        while (cin>>l>>r,l||r){
            if(r<l)swap(l,r);
    
            node a=sol(r);
            node b=sol(l-1);
    
            for(int i=0;i<=9;i++){
                if(i)cout<<" ";
                cout<<a.a[i]-b.a[i];
            }
            cout<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    云游四海
    保持良好的人际关系,赢得好人缘的八大诀窍
    二十三格经典的管理定律(建议收藏)
    游北湖公园有感
    如何成为领袖? 学习任正非小沃森郭士纳
    梦回江南
    观野花展有感
    爱一个人要爱多久
    醉卧山林
    游环岛路有感
  • 原文地址:https://www.cnblogs.com/sstealer/p/13296030.html
Copyright © 2011-2022 走看看