zoukankan      html  css  js  c++  java
  • BZOJ-1833-[ZJOI2010]count 数字计数(数位dp)

    Description

    给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次。

    Input

    输入文件中仅包含一行两个整数a、b,含义如上所述。

    Output

    输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次。

    Sample Input

    1 99

    Sample Output

    9 20 20 20 20 20 20 20 20 20

    HINT

    30%的数据中,a<=b<=10^6;
    100%的数据中,a<=b<=10^12。

    Source

     
    题解
    一道裸的数位dp
    dp[i][j][k]表示长度为i开头为j的数字中k的个数
    就当模板啦
     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 struct node{ ll a[10]; };
     5 ll a,b;
     6 ll t[15];
     7 node dp[15][10];
     8 node operator + (node x,node y){
     9     node t;
    10     for (int k=0;k<=9;k++)
    11         t.a[k]=x.a[k]+y.a[k];
    12     return t;
    13 }
    14 node calc(ll x){
    15     node ans;
    16     for (int i=0;i<=9;i++) ans.a[i]=0;
    17     if (!x){
    18         ans.a[0]=1;
    19         return ans;    
    20     }
    21     int len=12;
    22     while (t[len]>x) len--;
    23     ans.a[0]++;
    24     for (int i=1;i<len;i++)
    25         for (int j=1;j<=9;j++)
    26             ans=ans+dp[i][j];
    27     int cnt=x/t[len];
    28     for (int i=1;i<cnt;i++)
    29         ans=ans+dp[len][i];
    30     x%=t[len];
    31     ans.a[cnt]+=x+1;
    32     for (int i=len-1;i>=1;i--){
    33         cnt=x/t[i];
    34         for (int j=0;j<cnt;j++)
    35             ans=ans+dp[i][j];
    36         x%=t[i];
    37         ans.a[cnt]+=x+1;
    38     }
    39     return ans;
    40 }
    41 int main(){
    42     scanf("%lld%lld",&a,&b);
    43     t[1]=1;
    44     for (int i=2;i<=12;i++) t[i]=t[i-1]*10;
    45     for (int i=0;i<=9;i++)
    46         dp[1][i].a[i]=1;
    47     for (int i=2;i<=12;i++)
    48         for (int x=0;x<=9;x++)
    49             for (int y=0;y<=9;y++){
    50                 dp[i][y]=dp[i][y]+dp[i-1][x];
    51                 dp[i][y].a[y]+=t[i-1];
    52             }        
    53     node s1=calc(b),s2=calc(a-1);
    54     for (int i=0;i<9;i++)
    55         printf("%lld ",s1.a[i]-s2.a[i]);
    56     printf("%lld
    ",s1.a[9]-s2.a[9]);
    57     return 0;
    58 }
    View Code
  • 相关阅读:
    关于字节对齐以及内存占用
    关于HandlerThread的分析
    关于栈和队列的相关操作
    自定义控件(View的绘制流程源码解析)
    关于采用github.io搭建个人博客
    算法题解
    关于Android中ArrayMap/SparseArray比HashMap性能好的深入研究
    ADB server didn't ACK * failed to start daemon *
    Handler 、 Looper 、Message
    KMP字符串模式匹配详解(转)
  • 原文地址:https://www.cnblogs.com/zhuchenrui/p/7743417.html
Copyright © 2011-2022 走看看