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]);
}