POJ 3286 How many 0's(数位DP模板)

题目链接: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

POJ 3286 How many 0's(数位DP模板)的相关文章

TOJ 2294 POJ 3286 How many 0&#39;s? 数位dp

http://acm.tju.edu.cn/toj/showp2294.html http://poj.org/problem?id=3284 题外话:集训结束,回学校了.在宿舍看了这题,没什么好想法,去洗澡了.转了两个澡堂都特么没开..倒是在路上把这题想了.用回自己的电脑,不得不说苹果的字体渲染,真心高一个等级. 题意:给定两个数a和b,从a写到b,问一共写了多少个0. 分析:当然先转化为求0..a写多少个0.网上有更简单的做法,就是枚举每位作为0,则如果这一位本来是0,左边取1..a-1(不

POJ - 3286 - How many 0&#39;s? 【数位DP】

How many 0's? Time Limit: 1000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Description A Benedict monk No.16 writes down the decimal representations of all natural numbers between and including m and n, m ≤ n. How many 0's will he writ

POJ 3286 How many 0&#39;s?(多少0?)

POJ 3286 How many 0's?(多少0?) Time Limit: 1000MS   Memory Limit: 65536K [Description] [题目描述] A Benedict monk No.16 writes down the decimal representations of all natural numbers between and including m and n, m ≤ n. How many 0's will he write down? 一个

poj 3286 How many 0&#39;s? 按位统计

题意: 给m<=n,求从m写到n,一共写多少个0. 分析: 按位算当某位是0时左边有多少种情况,右边有多少种情况,注意左边的情况数为-1时(这时遍历到最高位)是为了把右边多加的情况减去,也就是把0作为开头时的情况减去. 代码: //poj 3286 //sep9 #include<iostream> using namespace std; typedef __int64 ll; ll b[16]; ll f(ll n) { ll left,m,ans=0; for(int i=1;i&

POJ 3286 How many 0&#39;s?

题目大意: 计算[m,n]之间所有数字有多少个零. 解题思路: 可以用[0,m)之间和[0,n]之间有多少个零然后作差. 规律是计算所有位置在到当前数时有多少个零. 下面是代码:   #include <set> #include <map> #include <queue> #include <math.h> #include <vector> #include <string> #include <stdio.h> #

POJ 3208 Apocalypse Someday 二分答案+数位DP

这题应该是POJ最强大的一道数位DP了吧 正解是AC自动机 不会 还是写数位DP吧 题目大意:我们令含有666的数字为不吉利数字,则可以得到一个递增数列: {an}=666,1666,2666,3666,4666,5666,6660,6661,.... 给定n,求an 首先我们把这个问题转化成另一个问题:给定n,求1~n中有多少个数含有666 解决了这个问题,把原问题二分答案即可 首先预处理f数组,令 f[i][0]表示i位数中首位不为6且不含666的数的数量 f[i][1]表示i位数中首位连续

数位dp模板 [dp][数位dp]

现在才想到要学数位dp,我是不是很弱 答案是肯定的 以一道自己瞎掰的题为模板 1 //题: 2 //输入数字n 3 //从0枚举到n,计算这n+1个数中含有两位数a的数的个数 4 //如12930含有两位数93 5 #include<cstdio> 6 #include<cstring> 7 #include<iostream> 8 using namespace std; 9 10 int n,m=0,a,g1,g2; 11 int dp[10][10][2],lim

数位dp模板

1 //HDU - 5787为例 2 //求区间[L,R]内,任意相邻k位(如果位数不足k,就是全部的数位)没有两两相同的数位的数的个数 3 LL l,r; 4 int k; 5 int num[20]; 6 LL dp[20][10010][5]; 7 //pos表示当前处理的位置(一般从高到低) 8 //limit是限制当前这位能否随便取,即决定top=num[pos]或top=9. 9 //非limit的状态可以记录起来,因为此时pos后面的数字都可以随便取,所以状态是一样的. 10 //

51nod 1009 - 数字1的数量 - [数位DP][模板的应用以及解释]

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1009 基准时间限制:1 秒 空间限制:131072 KB 给定一个十进制正整数N,写下从1开始,到N的所有正数,计算出其中出现所有1的个数. 例如:n = 12,包含了5个1.1,10,12共包含3个1,11包含2个1,总共5个1. Input 输入N(1 <= N <= 10^9) Output 输出包含1的个数 Input示例 12 Output示例