题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089

题意:求[n, m]区间内不含4和62的数字个数。

这题有两种思路,直接数位dp和dfs

数位dp:

  dp[i][j]表示i位数,首位是j的符合要求的数字个数。

  j = 4时    dp[i][j] = 0

  j != 4时

   

  例如求dp[3][2],2xx的个数,2已经确定了,2后面xx的个数即为2xx的个数,只用求出0x, 1x, 2x...9x的个数之和即可。同时要注意限制条件,dp[i][4]均为0,如果i位首位为6,i-1位首位为2的话也为0。这样我们首先预处理下,然后由此可以求区间内所符合要求的数字个数。

  以求[0, 365]为例,先求0xx, 1xx, 2xx, xx的个数即为每个的个数,当然如果是555的的话4xx是跳过的,或者前一位是6,那么2xx也要跳过。然后求[300, 365]的个数,已经确定首位为3,求3xx的个数,然后类似的确定xx的个数。如果遇到456这种情况,只用求0xx,1xx,2xx,3xx的个数,4xx就不用求了,因此最外层循环就可以停止了。类似的6223.. 没必要求[6200,6223]了。

代码:

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std; int dp[][];
int d[]; void init()
{
memset(dp, , sizeof(dp));
dp[][] = ;
for(int i = ; i <= ; i++)
for (int j = ; j <= ; j++)
for (int k = ; k <= ; k++)
if (j != && !(j== && k==))
dp[i][j] += dp[i-][k];
} int solve(int n)
{
int ans = , len = ;
while (n) {
d[++len] = n % ;
n /= ;
}
d[len+] = ;
for (int i = len; i >= ; i--) {
for (int j = ; j < d[i]; j++) {
if (d[i+] != || j != )
ans += dp[i][j];
}
if (d[i]== || (d[i+]== && d[i]==))
break;
}
return ans;
} int main()
{
freopen("1.txt", "r", stdin);
int n, m;
init();
while (~scanf("%d%d", &n, &m)) {
if (n + m == ) break;
printf("%d\n", solve(m+)-solve(n));
} return ;
}

DFS+记忆化搜索:

  dp[i][j]表示i位数,前一位数组是否为6的符合要求的个数。

  dfs的参数l是当前的位数,从最高位开始搜索。six是前一位是否为6,limit是最高位是否受限,如365,最高位就受限与0~3,然后开始搜索0xx, 1xx, 2xx, 3xx, 其中0xx,1xx,2xx中的xx都是不受限的,0~99均可取,而3xx中的xx要受65的限制,搜索下一位时继续设限。如果该位为4,或上一位为6,该位为2时就跳过不搜。另外搜索中有大量重复,所以采用记忆化搜索。如果受限的话就不能采用记忆化搜索的结果。

代码:

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std; int digit[], dp[][], v[][]; int dfs(int l, bool six, bool limit)
{
if (l == ) return ;
if (!limit && v[l][six]) return dp[l][six];
int len = limit ? digit[l] : ;
int nx = ;
for (int i = ; i <= len; i++) {
if ((i == ) || (six&&i==))
continue;
nx += dfs(l-, i==, limit&&(i==len));
}
if (!limit) {
v[l][six] = true;
dp[l][six] = nx;
}
return nx;
} int sum(int n)
{
memset(dp, , sizeof(dp));
memset(v, , sizeof(v));
int pos = ;
while (n) {
digit[++pos] = n % ;
n /= ;
}
int ans = dfs(pos, false, true);
return ans;
}
int main()
{
//freopen("1.txt", "r", stdin);
int n, m;
while (~scanf("%d%d", &n, &m)) {
if (n + m == ) break;
printf("%d\n", sum(m)-sum(n-));
} return ;
}

ps:注意两者在[n, m]时的处理。

  

  

[hdu 2089] 不要62 数位dp|dfs 入门的更多相关文章

  1. Hdu 2089 不要62 (数位dp入门题目)

    题目链接: Hdu 2089 不要62 题目描述: 给一个区间 [L, R] ,问区间内不含有4和62的数字有多少个? 解题思路: 以前也做过这个题目,但是空间复杂度是n.如果数据范围太大就GG了.今 ...

  2. HDU 2089 - 不要62 - [数位DP][入门题]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 Time Limit: 1000/1000 MS (Java/Others) Memory Li ...

  3. HDU 2089 不要62 数位DP模板题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 参考博客:https://www.cnblogs.com/HDUjackyan/p/914215 ...

  4. HDU 2089 不要62(数位DP&#183;记忆化搜索)

    题意  中文 最基础的数位DP  这题好像也能够直接暴力来做   令dp[i][j]表示以 j 开头的 i 位数有多少个满足条件 那么非常easy有状态转移方程 dp[i][j] = sum{ dp[ ...

  5. hdu 2089 不要62 数位dp

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

  6. hdu 2089 不要62 (数位dp基础题)

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

  7. hdu 2089不要62 (数位dp)

    Problem Description 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer). 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来 ...

  8. hud 2089 不要62 (数位dp)

    #include<stdio.h> #include<string.h> #include<math.h> #define max 10 ]; int number ...

  9. HDU 3652 B-number (数位DP,入门)

    题意: 如果一个整数能被13整除,且其含有子串13的,称为"B数",问[1,n]中有多少个B数? 思路: 这题不要用那个DFS的模板估计很快秒了. 状态设计为dp[位数][前缀][ ...

随机推荐

  1. hihoCoder#1139(二分+bfs)

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回和上上回里我们知道Nettle在玩<艦これ>,Nettle在整理好舰队之后终于准备出海捞船和敌军交战了 ...

  2. 机器学习:PCA(使用梯度上升法求解数据主成分 Ⅰ )

    一.目标函数的梯度求解公式 PCA 降维的具体实现,转变为: 方案:梯度上升法优化效用函数,找到其最大值时对应的主成分 w : 效用函数中,向量 w 是变量: 在最终要求取降维后的数据集时,w 是参数 ...

  3. 分析诊断工具之五:Procedure Analyse优化表结构

    一.Procedure Analyse PROCEDURE ANALYSE() ,在优化表结构时可以辅助参考分析语句.通过分析select查询结果对现有的表的每一列给出优化的建议. 利用此语句,MyS ...

  4. 【OpenCV】图像代数运算:平均值去噪,减去背景

    代数运算,就是对两幅图像的点之间进行加.减.乘.除的运算.四种运算相应的公式为: 代数运算中比较常用的是图像相加和相减.图像相加常用来求平均值去除addtive噪声或者实现二次曝光(double-ex ...

  5. docker 安装mysql 使用navicat访问 解决

    1. 下载Mysql的Docker镜像: 2. 运行镜像,设置root账号初始密码(123456),映射本地宿主机端口3306到Docker端口3306.测试过程没有挂载本地数据盘: 3. 查看已运行 ...

  6. Canopy聚类算法(经典,看图就明白)

    只有这个算法思想比较对,其他 的都没有一开始的remove: 原网址:http://www.shahuwang.com/?p=1021 Canopy Clustering 这个算法是2000年提出来的 ...

  7. 如何使32位Linux支持4G以上内存

    问题 Linux无法支持超过4G的内存,笔者使用的Linux是CentOS 5,机器是DELL PE1950服务器.    原因: X86系统默认寻址能力的限制    解决办法: 安装具有PAE(物理 ...

  8. Java连接mysql数据库攻略

    一. 软件下载 Mysql 下载版本:4.1.11 http://dev.mysql.com/downloads/mysql/4.1.html JDBC驱动 下载版本:3.1.8 http://dev ...

  9. Java中自动装箱代码初探

    <深入理解Java虚拟机>中讲语法糖时,提到了下面这个例子(不是原文中的例子,我自己改过): public class AutoBoxingTest { /** * @param args ...

  10. 记工作的变化--入住DB

    2013年11月1日----一个值得纪念的日子! 今天才是我作为一个劳动者,步入社会的真正开始. 以前一直觉得做技术的技术做好就行了不用在意其余的细节.现实是做人(沟通)比做技术更重要! 以前一直觉得 ...