zoukankan      html  css  js  c++  java
  • bzoj1833: [ZJOI2010]count 数字计数

    题意:

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

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

    题解:

    第一道数位dp题。。

    统计出1-x内每种数码出现次数,由前缀和思想答案为f[b]-f[a-1]

    f[x,y]表示当前考虑到第x位,数码y出现的次数,注意到数据范围应为ll

    状态转移对除0外的数为f[x-1,y]*9+tp[i-1](意义即为当前为枚举1-9,后面出现y的次数+当前位为y)

    对于0进行一些细节处理,即首位不能放0(但之后是可以的) #比如不要把0001这样的0统计进去

    之后统计答案的时候,只需从高位到低位考虑

    例如8765 只需先算1-7999 再算8000-8700。。。。。。以此类推

    代码:

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    ll n,m,dp[30][30],tp[30],a[30],b[30],pp[30];
    char st[30];
    void js(ll oo[30],ll x) {
        ll tmp[30];
        memset(tmp,0,sizeof(tmp));
        bool tt=false;
        while (x!=0) 
        {
            ll i=x,j=0;
            while (i>=10) i=i/10,j++;
            ll p=i;
            if (tt==false)
            {
                for (ll i=1; i<=p-1;i++)
                tmp[i]+=pp[j+1];
                for (ll i=1; i<=9; i++)
              tmp[i]+=p*dp[j][i];
              tmp[0]+=(p-1)*dp[j][0]+tp[j];
              tt=true;
          } else
          {
              for (ll i=0; i<=p-1;i++)
                tmp[i]+=pp[j+1];
             for (ll i=0; i<=9; i++)
              tmp[i]+=p*dp[j][i];
          }
          sprintf(st,"%lld",x);
            ll ii=0;
            for (ii=0; ii<=1ll*strlen(st)-2;ii++)
              if (st[ii+1]!='0') break;
            tmp[0]+=(x-p*pp[j+1]+1)*ii;
          tmp[p]+=x-p*pp[j+1]+1;
            x=x-p*pp[j+1];
        }
        memcpy(oo,tmp,sizeof(tmp));
    };
    int main() {
        freopen("noip.in","r",stdin);
        freopen("noip.out","w",stdout);
        pp[1]=1;
        for (ll i=1; i<=13; i++) {
            pp[i+1]=pp[i]*10;
            for (ll j=0; j<=9; j++)
                dp[i][j]=dp[i-1][j]*10+pp[i];
            tp[i]=dp[i-1][0]*9+tp[i-1];
        }
        tp[1]=1;
        cin>>n>>m;
        if (n!=1) js(a,n-1);
        js(b,m);
        for (ll i=0; i<=8; i++) cout<<(b[i]-a[i])<<" ";
        cout<<(b[9]-a[9]);
        return(0);
    }
  • 相关阅读:
    怎样建设一个比较好的地方性商业门户网站
    地方门户网站如何推广
    【转】地方门户网站:地区细分领域的蓝海市场
    【转】测试人员可能会遇到的问题
    【转】工作反思-跳槽篇
    简单验证码识别 tessnet2
    log4net使用详解
    java理论基础学习三
    java理论基础学习二
    java理论基础学习一
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8138034.html
Copyright © 2011-2022 走看看