bzoj 1833: [ZJOI2010]count 数字计数

Time Limit: 3 Sec Memory Limit: 64 MB
Submit: 4533 Solved: 2055
[Submit][Status][Discuss]
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。

解题思路

f[i][j][k] 表示i位,开头位j,k这个数出现的次数,先预处理出f数组。细节比较多。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int MAXN = 13;
typedef long long LL;

LL a,b;
LL mul[MAXN];
struct Dight{
    LL a[MAXN];
    Dight(){memset(a,0,sizeof(a));}
}f[MAXN][MAXN];

Dight operator +(Dight A,Dight B){
    for(register int i=0;i<=9;i++)
        A.a[i]+=B.a[i];
    return A;
}

Dight operator -(Dight A,Dight B){
    for(register int i=0;i<=9;i++)
        A.a[i]-=B.a[i];
    return A;
}

inline Dight calc(LL x){
    Dight sum;
    sum.a[0]=1;
    if(x==0) return sum;
    int len=13;
    while(x<=mul[len]) len--;
    for(register int i=1;i<len;i++) 
        for(register int j=1;j<=9;j++)
            sum=sum+f[i][j];
    int cur=x/mul[len];
    for(register int i=1;i<cur;i++)
        sum=sum+f[len][i];
    x%=mul[len];sum.a[cur]+=x+1;
    for(register int i=len-1;i;i--){
        cur=x/mul[i];
        for(register int j=0;j<cur;j++)
            sum=sum+f[i][j];
        x%=mul[i];
        sum.a[cur]+=x+1;
    }
    return sum;
}

int main(){
    scanf("%lld%lld",&a,&b);
    mul[1]=1;
    for(register int i=2;i<=13;i++) 
        mul[i]=mul[i-1]*10ll;
    for(register int i=0;i<=9;i++)
        f[1][i].a[i]=1;
    for(register int i=2;i<=12;i++) 
        for(register int j=0;j<=9;j++)
            for(register int k=0;k<=9;k++){
                f[i][j]=f[i][j]+f[i-1][k];
                f[i][j].a[j]+=mul[i-1];
            }
//  for(register int i=1;i<=2;i++)  
//      for(register int j=0;j<=9;j++)
//          for(register int k=0;k<=9;k++)
//              printf("f[%d][%d][%d]=%d
",i,j,k,f[i][j].a[k]);            
    Dight ans=calc(b)-calc(a-1);
    for(register int i=0;i<=9;i++)
        printf("%lld ",ans.a[i]);
}
原文地址:https://www.cnblogs.com/sdfzsyq/p/9676918.html