LuoguP2602 [ZJOI2010]数字计数【数位dp】By cellur925

题目传送门

题目大意:给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次。


继续数位dp=w=。

这一次我们不需要记录$pre$啦!(撒花)。

因为这次我们需要的是统计个数!那么我们就可以针对每个数字,搞一次记搜。记搜的时候只要注意传递下当前的数字个数就行了。

当然了我们还是需要关注下前导0的,如果现在还是前导0呢,那么肯定不能计数了...

Code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 typedef long long ll;
 7 
 8 int len;
 9 int border[20];
10 ll l,r;
11 ll dp[20][20];
12 
13 ll dfs(int pos,int sum,int ling,int limit,int num)
14 {
15     if(pos<1) return sum;
16     if(!limit&&dp[pos][sum]!=-1&&!ling) return dp[pos][sum];
17     ll tmp=0;
18     ll lim=limit ? border[pos] : 9;
19     for(int i=0;i<=lim;i++)
20     {
21         if(ling&&i==0) tmp+=dfs(pos-1,0,1,limit&&i==lim,num);
22         else tmp+=dfs(pos-1,sum+(i==num ? 1 : 0),0,limit&&i==lim,num);
23     } 
24     if(!ling&&!limit) dp[pos][sum]=tmp;
25     return tmp;
26 }
27 
28 ll work(ll x,int num)
29 {
30     len=0;
31     memset(dp,-1,sizeof(dp));
32     while(x)
33     {
34         border[++len]=x%10;
35         x/=10;
36     }
37     return dfs(len,0,1,1,num);
38 }
39 
40 int main()
41 {
42     scanf("%lld%lld",&l,&r);
43     for(int i=0;i<=9;i++)
44         printf("%lld ",work(r,i)-work(l-1,i));
45     return 0;
46 }
View Code
原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9788197.html