题目链接:http://poj.org/problem?id=3286
题目大意:
输入n,m,求[n,m]的所有数字中,0出现的总数是多少,前导零不算。
解题思路:
模板题,设dp[pos][num],pos为数位,num为当前0的数目,然后套数位DP模板即可。
还有之前的一些思考:
关于数位DP求0时,dp下标记录num有什么作用,num不是与后面的0的个数无关吗?
是的,在(!limit&&!lead)的情况下,前面有多少0是不影响后面可以出现多少0的。
但是,比如说dp[pos][num]吧,dp[1][0]=10,但是dp[1][1]=11,这样应该有点明白了吧,
虽然后面有多少0不影响,但是记忆化的结果加上了前面的0的数量num,这样前面的num就
需要当做下标记录下来了,不同的num对应的记忆化结果是不一样的。
代码
1 #include<cstdio> 2 #include<cmath> 3 #include<cctype> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #include<set> 10 #include<map> 11 #include<stack> 12 #include<string> 13 #define lc(a) (a<<1) 14 #define rc(a) (a<<1|1) 15 #define MID(a,b) ((a+b)>>1) 16 #define fin(name) freopen(name,"r",stdin) 17 #define fout(name) freopen(name,"w",stdout) 18 #define clr(arr,val) memset(arr,val,sizeof(arr)) 19 #define _for(i,start,end) for(int i=start;i<=end;i++) 20 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0); 21 using namespace std; 22 typedef long long LL; 23 const int N=5e6+5; 24 const int INF=0x3f3f3f3f; 25 const double eps=1e-10; 26 27 LL top[105]; 28 LL dp[50][50]; 29 30 LL dfs(bool limit,bool lead,LL pos,LL num){ 31 if(pos==-1) 32 return num; 33 if(!limit&&!lead&&dp[pos][num]!=-1) return dp[pos][num]; 34 LL up=limit?top[pos]:9; 35 LL ans=0; 36 for(int i=0;i<=up;i++){ 37 ans+=dfs(limit&&i==up,lead&&i==0,pos-1,num+(i==0&&!lead)); 38 } 39 if(!lead&&!limit) dp[pos][num]=ans; 40 return ans; 41 } 42 43 LL solve(LL x){ 44 memset(dp,-1,sizeof(dp)); 45 int cnt=-1; 46 while(x){ 47 top[++cnt]=x%10; 48 x/=10; 49 } 50 return dfs(1,1,cnt,0); 51 } 52 53 int main(){ 54 FAST_IO; 55 LL l,r; 56 while(cin>>l>>r){ 57 if(l==-1&&r==-1) 58 break; 59 LL ans=0; 60 if(l==0) l++,ans++; 61 ans+=solve(r)-solve(l-1); 62 cout<<ans<<endl; 63 } 64 return 0; 65 }
POJ 3286 How many 0's(数位DP模板)
原文地址:https://www.cnblogs.com/fu3638/p/8953595.html
时间: 2024-11-08 01:01:56