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 }
独立意志与自由思想是必须争的,且须以生死力争。