#P2983. USACO(37)数位1:区间数字的个数[Dream Counting, 2006 Dec]
USACO(37)数位1:区间数字的个数[Dream Counting, 2006 Dec]
Description
【题意】在区间 $[A , B]$ ,$0$ 到 $9$ 这十个数字,分别出现了多少次?
【输入格式】
一行两个整数 $A$ 和 $B$,$1 \le A \le B \le 10^{18}$
【输出格式】
十个整数:依次表示 $0$ 到 $9$ 在区间 $[A , B]$ 出现的次数
【样例输入】
129 137
【样例输出】
1 10 2 9 1 1 1 1 0 1
Hint
by hansang:#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=35;
struct node{
LL a[15], s;
node(){s=0; memset(a, 0, sizeof(a));}
}f[N][15]; LL a[N];
node operator+(node n1, node n2){
for(int i=0; i<=9; i++)
n1.a[i]+=n2.a[i];
n1.s+=n2.s;
return n1;
}
node operator-(node n1, node n2){
for(int i=0; i<=9; i++)
n1.a[i]-=n2.a[i];
return n1;
}
node operator*(node no, LL x){
for(int i=0; i<=9; i++)
no.a[i]*=x;
return no;
}
node calc(LL x){
int len=0; node ans, sum;
while(x>0) a[++len]=x%10, x/=10;
for(int i=len; i>=1; i--){
for(int j=(i==len)? 1: 0; j<a[i]; j++){
ans=ans+f[i][j];
ans=ans+sum*f[i][j].s;
}
sum.a[a[i]]++;
if(i==1){
for(int j=1; j<=len; j++){
ans.a[a[j]]++;
}
}
}
for(int i=len-1; i>=1; i--)
for(int j=1; j<=9; j++){
ans=ans+f[i][j];
}
return ans;
}
int main(){
for(int i=0; i<=9; i++){
f[1][i].a[i]=1;
f[1][i].s=1;
}
for(int i=2; i<=30; i++)
for(int j=0; j<=9; j++)
for(int k=0; k<=9; k++){
f[i][j]=f[i][j]+f[i-1][j];
f[i][j].a[k]+=f[i-1][j].s;
}
LL a, b; scanf("%lld%lld", &a, &b);
node no=calc(b)-calc(a-1);
for(int i=0; i<=9; i++) printf("%lld ", no.a[i]);
printf("\n");
return 0;
}