bzoj1833 [ZJOI2010]count 数字计数

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。

 

正解:数位$dp$。

简单数位$dp$,直接记录每一位的数字个数然后计算答案即可。

 

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 
 6 using namespace std;
 7 
 8 struct data{ ll a[10]; }f[15][2],IE;
 9 
10 int vis[15][2],st[15],top;
11 ll g[15][2],ans[10],l,r;
12 
13 il ll dfs1(RG int pos,RG int lim){
14   if (!pos) return 1;
15   if (g[pos][lim]!=-1) return g[pos][lim];
16   RG int end=lim?st[pos]:9; RG ll res=0;
17   for (RG int i=0;i<=end;++i)
18     res+=dfs1(pos-1,lim && i==end);
19   return g[pos][lim]=res;
20 }
21 
22 il data dfs2(RG int pos,RG int lim){
23   if (!pos) return IE;
24   if (vis[pos][lim]) return f[pos][lim]; vis[pos][lim]=1;
25   for (RG int i=0;i<=9;++i) f[pos][lim].a[i]=0;
26   RG int end=lim?st[pos]:9;
27   for (RG int i=0;i<=end;++i){
28     RG data res=dfs2(pos-1,lim && i==end);
29     for (RG int j=0;j<=9;++j) f[pos][lim].a[j]+=res.a[j];
30     f[pos][lim].a[i]+=dfs1(pos-1,lim && i==end);
31   }
32   return f[pos][lim];
33 }
34 
35 il void solve(RG ll n,RG int fg){
36   top=0; while (n) st[++top]=n%10,n/=10;
37   memset(g,-1,sizeof(g)),memset(vis,0,sizeof(vis));
38   RG data res=dfs2(top,1);
39   for (RG int i=top;i;--i) ans[0]-=fg*dfs1(i-1,0);
40   for (RG int i=0;i<=9;++i) ans[i]+=fg*res.a[i]; return;
41 }
42 
43 int main(){
44 #ifndef ONLINE_JUDGE
45   freopen("count.in","r",stdin);
46   freopen("count.out","w",stdout);
47 #endif
48   cin>>l>>r,solve(r,1),solve(l-1,-1),printf("%lld",ans[0]);
49   for (RG int i=1;i<=9;++i) printf(" %lld",ans[i]); return 0;
50 }

 

posted @ 2017-11-06 22:51  wfj_2048  阅读(138)  评论(0编辑  收藏  举报