bzoj1833 [ZJOI2010]count 数字计数

Description

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

Input

仅包含一行两个整数ab,含义如上所述。

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<=106;

100%的数据中,a<=b<=1012。

本题数据范围10的12次方,暴力枚举当然不行,我刚开始想打表来着(发现规律了)

比如说一个数342567456

可以预处理最高位3的个数,之后是4,然后是2...

拆分成12个子问题求解(前缀和).

#include<stdio.h>
long long a,b,i;
long long f[13],shi[13];
long long cnt[13];
long long cnta[13],cntb[13];
void play(long long x,long long cnt[])
{
	long long number[13];
	int len=0;
    while(x)
    {
        number[++len]=x%10;
        x/=10;
    } 
    for(int i=len;i>0;i--)
    {
		long long ans=0;
  		for(int j=i-1;j>=1;j--)
            ans=ans*10+number[j];
        for(int j=0;j<=9;j++)
        	cnt[j]+=f[i-1]*number[i];
        for(int j=0;j<number[i];j++)
        	cnt[j]+=shi[i-1];      
        cnt[number[i]]+=ans+1;
        cnt[0]-=shi[i-1];
    }
}
int main()
{
	scanf("%lld%lld",&a,&b);
    shi[0]=1;
    for(int i=1;i<=12;i++)
    {
        f[i]=f[i-1]*10+shi[i-1];
        shi[i]=10*shi[i-1];
    }
    play(a-1,cnta);
    play(b,cntb);
    for(int i=0;i<=8;i++)
    	printf("%lld ",cntb[i]-cnta[i]);
	printf("%lld",cntb[9]-cnta[9]);		
}



猜你喜欢

转载自blog.csdn.net/zyq_20030305/article/details/79149861