类型:数位DP

传送门:>Here<

题意:问区间$[n,m]$的数字中,不含4以及62的数字总数

解题思路

数位DP入门题

先考虑一般的暴力做法,整个区间扫一遍,判断每个数是否合法并累计答案。而数位DP则认为可以换一种方法来枚举,找到对于一个数的上限,然后在这个限度内枚举每一个数位来统计答案

为了方便数位DP,题意可以转化求区间$[0, k]$的符合要求的数字总数,因此答案就是$ans(M)-ans(N-1)$

首先我们可以预处理出dp数组:$dp[i][j]$表示以$j$开头的$i$位数的符合要求的数字总数;例如,$dp[2][3]$表示以3开头的2位数中符合要求的,也就是区间$[30, 39]$中符合要求的。$$dp[i][j] = \sum\limits_{0 \leq k \leq 9 \\ \ k \neq 4}dp[i-1][k]$$这个方程很好理解,相当于枚举一个数位塞到前面,同时需要保证不能把6塞当2前面,并且特判一下4就好了

至于统计答案,我们从上限的最高位开始往下扫描。这里有个很巧妙的思想——每次处理不超过当前这一位的部分。形象地说,对于数字$21358$,最高位扫描$0~1$,也就是把答案累积上$dp[5][0~1]$。这一步相当于处理了区间$[0, 19999]$中的所有;此时默认最高位是2,扫描到下一位,累积$dp[4][0~0]$,也就相当于处理了区间$[20000,20999]$;依次类推,然后将会处理$[21000,21299]$,$[21300,21349]$,$[21350,21357]$。因此我们可以在$O(lg N * 10)$的复杂度内处理区间$[0, N-1]$。(注意不包括N)$$ans = \sum\limits_{i=num}^{1}\sum\limits_{j=0}^{digit[i]-1}dp[i][j]$$

然后在来看判断62和4的问题:每当我们进入到下一位,我们就将默认上一位确定。此时若确定的那一位为4,那么之后的都不用考虑了(一定不合法)。同理,如果当前确定的为2且上一位确定的为6,那么也可以跳出。事实上,这个跳出不是优化,而是必须那么做——如果不跳出,就会错误地累积很多答案。同时,不仅进入下一位的时候要判断,扫描的时候也要判断。道理一样

拓展:如果题目要求的不是【不要62】而是【要62】呢?就好像[HDU3555] Bomb所要求的一样,只需要求出所有的【不要62】数字,用N减一下就好了

Code

特别需要注意的是$digit[num+1]==0$这一步的处理,如果不加这一步,那么如果在处理前一个数字时残留下了$digit[num+1]==6$,那么你的程序将不能在最高位填充2了!

另外还有dp数组的初始化问题:一种是$dp[0][0]=1$,或者对于所有$i \neq 4$,$dp[1][i]=1$。其实这两者是等效的,因为在统计$dp[1][i]$时,只会累积到$dp[0][0]$为1

/*By DennyQi 2018.8.13*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define r read()
#define Max(a,b) (((a)>(b)) ? (a) : (b))
#define Min(a,b) (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int MAXN = ;
const int MAXM = ;
const int INF = ;
inline int read(){
int x = ; int w = ; register int c = getchar();
while(c ^ '-' && (c < '' || c > '')) c = getchar();
if(c == '-') w = -, c = getchar();
while(c >= '' && c <= '') x = (x << ) + (x << ) + c - '', c = getchar(); return x * w;
}
int N,M,num,X,Y;
int dp[][],digit[];
inline void Init(){
dp[][] = ;
for(int i = ; i <= ; ++i){
for(int j = ; j <= ; ++j){
if(j == ) continue;
for(int k = ; k <= ; ++k){
if(k == && j == ) continue;
dp[i][j] += dp[i-][k];
}
}
}
}
inline int cul(int x){
num = ;
int y = x, res = ;
while(y > ){
digit[++num] = y % ;
y /= ;
}
digit[num+] = -;
for(int i = num; i >= ; --i){
for(int j = ; j < digit[i]; ++j){
if(digit[i+] == && j == ) continue;
res += dp[i][j];
}
if(digit[i] == || (digit[i+]==&&digit[i]==)) break;
}
return res;
}
int main(){
Init();
for(;;){
N = r, M = r;
if(!N && !M) break;
printf("%d\n",cul(M+)-cul(N));
}
return ;
}

☆ [HDU2089] 不要62「数位DP」的更多相关文章

  1. HDU2089 ------不要62(数位dp)

    不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  2. HDU2089 不要62 题解 数位DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 题目大意:求区间 \([l,r]\) 范围内不包含数字"4"且不包含连续的数 ...

  3. hdu2089不要62(数位dp)

    #include <stdio.h> #include <string.h> ][]; ]; /* dp[i][0] 不含62,4 dp[i][1] 2开头 dp[i][2] ...

  4. HDU 2089 不要62(数位dp入门)

    题意:统计区间 [a,b] 中不含 4 和 62 的数字有多少个. 题解:这是数位DP的入门题了,首先要理解数DP的原理,DP[i][j]:代表第i位的第j值,举个栗子:如4715   数位数是从右向 ...

  5. hdu2089 不要62--经典数位DP

    一道十分经典的数位DP的题目. dp[i][j]表示最高位是数字i,连同最高位在内共有j位.注意边界的初始化. 接下来就是区间划分,特殊情况处理.....对了,如果不知道自己的方法是否正确,可以写一个 ...

  6. HDU 2089 不要62 【数位dp】

    <题目链接> 不要62 Problem Description 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer).杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照 ...

  7. HDU 2089 不要62(数位dp模板题)

    http://acm.hdu.edu.cn/showproblem.php?pid=2089 题意:求区间内不包含4和连续62的数的个数. 思路: 简单的数位dp模板题.给大家推荐一个好的讲解博客.h ...

  8. HDU 2089 不要62【数位DP入门题】

    不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  9. 【ACM】不要62 (数位DP)

    题目:http://acm.acmcoder.com/showproblem.php?pid=2089 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer).杭州交通管理局经常会扩充一些的士车牌照,新 ...

随机推荐

  1. Entity Framework Core系列之什么是Entity Framework Core

    前言 Entity Framework Core (EF Core)是微软推荐的基于.NET Core framework的应用程序数据访问技术.它是轻量级,可扩展并且支持跨平台开发.EF Core是 ...

  2. Redux 入门教程(三):React-Redux 的用法

    为了方便使用,Redux 的作者封装了一个 React 专用的库 React-Redux,本文主要介绍它. 这个库是可以选用的.实际项目中,你应该权衡一下,是直接使用 Redux,还是使用 React ...

  3. dfs实现数的全排列

    代码 #include<bits/stdc++.h> using namespace std; #define ll long long bool vis[15]; int a[15]; ...

  4. Factors of Factorial AtCoder - 2286 (N的阶乘的因子个数)(数论)

    Problem Statement You are given an integer N. Find the number of the positive divisors of N!, modulo ...

  5. iOS上手指点击波纹效果的实现

    https://www.jianshu.com/p/35e6f53ca0fe 2016.10.19 22:00* 字数 135 阅读 2468评论 2喜欢 7 闲暇时间做了一个反馈手指点击屏幕的效果, ...

  6. 如何优化Docker储存

    大家在使用Docker的过程中,有没有想过,Docker在本地存储镜像时把文件存储在哪里了呢?有没有对文件的总大小做一定的限制呢?能不能调整本地存储的位置及总限制大小呢?今天,我们就从这些问题入手,来 ...

  7. B-Tree 和 B+Tree

    B-Tree和B+Tree 本文来自 Hubery_James 的CSDN 博客 ,全文地址请点击:原文地址-干货满满 B+树索引是B+树在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索 ...

  8. scrapy之环境安装

    scrapy之环境安装 在之前我安装了scrapy,但是在pycharm中却无法使用. 具体情况是: 我的电脑上存在多个python,有python2,python3,anaconda,其中anaco ...

  9. MySQL左连接时 返回的记录条数 比 左边表 数量多

    在学MySQL的连接时,为了便于记忆,就将左连接 记做 最后结果的总记录数 和 进行左连接的左表的记录数相同,简单的说就是下面这个公式 count(table A left join table B) ...

  10. mysql cpu 100% 满 优化方案

    解决MySQL CPU占用100%的经验总结 - karl_han的专栏 - CSDN博客 https://blog.csdn.net/karl_han/article/details/5630782 ...