1833: [ZJOI2010]count 数字计数
Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 4334 Solved: 1923
[ 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。
Source
题解:原来我大ZJOI史上也有这种水题啊QAQ
现在都难得不成样子。
就是个数位dp就好了呀,yy一下就能搞出来了。
代码:
#include<bits/stdc++.h>
using namespace std;
long long n,m,t,a[1000],f[100][100][100],sum[100],aa[100];
long long solve(long long x,long long pd){
int len=0,i,j,k;
long long ans=0,xx=x;
while(x){
len++;
a[len]=x%10;
x/=10;
}
for(i=1;i<len;i++)
for(j=1;j<=9;j++)
for(k=0;k<=9;k++)sum[k]+=f[i][j][k]*pd;
for(i=len;i;i--){
sum[a[i]]+=(xx%aa[i]+1)*pd;
for(j=0;j<a[i];j++)
if((j)||(j==0&&i<len))
for(k=0;k<=9;k++)sum[k]+=f[i][j][k]*pd;
}
}
int main(){
int i,j,k,ii;
scanf("%lld%lld",&n,&m);
t=1;aa[1]=1;
for(i=0;i<=9;i++)f[1][i][i]=1;
for(i=2;i<=13;i++){
t*=10;
aa[i]=t;
for(j=0;j<=9;j++){
for(k=0;k<=9;k++)
for(ii=0;ii<=9;ii++)
f[i][j][k]+=f[i-1][ii][k];
f[i][j][j]+=t;
}
}
solve(m,1);solve(n-1,-1);
for(i=0;i<9;i++)printf("%lld ",sum[i]);
printf("%lld",sum[9]);
}