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 }