zoukankan      html  css  js  c++  java
  • [BZOJ 1833] 数字计数

    Link:

    BZOJ 1833 传送门

    Solution:

    比较明显的数位DP

    先预处理出1~9和包括前导0的0的个数:$pre[i]=pre[i-1]*10+10^{digit-1}$

    (可以分为首位和其它位来考虑问题)

    求$(L,R)$的个数,可以用$(1,R)-(1,L-1)$差分来做

    在求$(1,K)$时,我们先根据预处理的值算出$[0,999....99]$的值(不受边界影响)

    接下来从最高位开始尽可能增加$10^n$,直到达到边界后再开始增加$10^{n-1}$

    每次对于前面已确定的部分暴力算,而后面不确定的、可任意取值的直接用$pre[i]$统计

    Code:

    #include <bits/stdc++.h>  
    using namespace std;  
    typedef long long ll;  
    ll res[10],pre[20];  
    
    void split(ll x,ll pos){while(x) res[x%10]+=pos,x/=10;}
    void Digital_DP(ll x,int flag)  
    {  
        int i,j;ll pos=10,now;  
        for(i=1;pos<x;i++)//对[0,99..99]进行统计
        {  
            for(j=0;j<=9;j++)  
                res[j]+=pre[i-1]*9*flag;  
            for(j=1;j<=9;j++)  
                res[j]+=pos/10*flag;
            pos*=10;
        }
        
        now=pos/=10;i--;
        while(now<x)  
        {  
            while(now+pos<=x)  
            {  
                ll temp=now/pos;
                split(temp,pos*flag);//对已确定部分的暴力统计
                for(j=0;j<=9;j++)//对可任意取值部分的统一计算
                    res[j]+=pre[i]*flag;           
                now+=pos;  
            }
            pos/=10;i--;
        }  
    }  
    int main()  
    {  
        int i;ll a,b,pos=10;  
        pre[1]=1;
        for(i=2;i<=12;i++)  
            pre[i]=pre[i-1]*10+pos,pos*=10;  
        
        cin >> a >> b;
        Digital_DP(b+1,1);Digital_DP(a,-1);
        for(i=0;i<=9;i++) cout << res[i] << " ";
    }  

    Review:

    1、对于所有i位中每个数字出现次数的预处理要积累:

    $pre[i]=pre[i-1]*10+10^{digit-1}$

    2、数位统计中的区间问题,考虑差分,都化为$(1,K)$的形式进行求解

    3、数位DP中,特殊处理边界;数字出现次数,特殊处理前导0

  • 相关阅读:
    abstract修饰方法总结
    linux tar.gz zip 解压缩 压缩命令
    html5视频播放
    Response.Redirect 打开新窗体的两种方法
    Gmail POP3设置
    加壳学习笔记(二)-汇编基础
    C#-异常处理:tyr,catch,finally ---ShinePans
    cocos2d jsb 打包 Android APK
    编写你自己的单点登录(SSO)服务
    一分钟制作U盘版BT3
  • 原文地址:https://www.cnblogs.com/newera/p/9080152.html
Copyright © 2011-2022 走看看