POJ3208 启示录

题目传送门

题目大意:我们称只要某数字的十进制表示中有三个连续的6,我们就称它为“魔鬼数”,比如:666,1666,6663,16666 等。现给出一个数X,求“第X小的魔鬼数”。X≤5×107X\le 5\times 10^7X≤5×107,一共有T组数据点,T≤1000T\le1000T≤1000。

part.1part.1part.1 引入

这一道题显然是一道数位DP的题目,那么我们先来了解一下什么是数位DP

众所周知
数位DP是与数字相关的一类计数问题,它往往指的是这样的题型:

给定一个闭区间 [l,r][l,r][l,r],让你求这个区间中满足某种条件的数的个数。

对于这类题目,我们通常先用动态规划进行预处理,再基于拼凑思想,用“试填法”求出最终的答案。

part.2part .2part.2具体分析

面对这样的一道题,如果直接每次都枚举到第X个“魔鬼数”,肯定会超时。那么我们思考一下如何解决这个问题呢?

其实,这是一道数位DP的典型例题,根据其通常做法,我们可以打出一个表记录一下魔鬼数的个数,然后通过一些
玄学 ”的处理,来巧妙计算出第X个“魔鬼数”

part.3part.3part.3 步骤实现

1.1.1. 预处理

我们设F[i,3]F [i,3]F[i,3]表示由i位数字构成的魔鬼数有多少个,
F[i,j](0≤j≤2)F [i,j] (0\le j \le2 )F[i,j](0≤j≤2) 表示由iii位数字构成,开头已经有连续jjj个6的非魔鬼数有多少个。(注意:在计算F时,我们允许前导0存在)。

实际上,在这里**F[i,3]F [i,3]F[i,3] 与 F[i,j]F[i,j]F[i,j]具有的含义是不同的。所以这两者不是以同一种方式转移的**

对于F [i,3i,3i,3] :它代表的是由iii位数字组成含有连续3个6的总方案数,这里的6并不一定从第iii位开始,

然而对于F [i,ji,ji,j] :它代表的是从第iii位开始的有jjj个6的方案数。

那么,在考虑第iii位(最高位)是什么数字时,易得转移方程:

  • F[i,0]F [i,0]F[i,0] = 9×9\times9×(F[i−1,0]+F[i−1,1]+F[i−1,2])F[i-1,0]+F[i-1,1]+F[i-1,2])F[i−1,0]+F[i−1,1]+F[i−1,2])
  • F[i,1]=F[i−1,1]F [i,1] = F [i-1,1]F[i,1]=F[i−1,1]
  • F[i,2]=F[i−1,2]F [i,2] = F [i-1,2]F[i,2]=F[i−1,2]

简要概述一下上述转移方程:

首先,对于j=0j=0j=0 的情况,即第iii位不放6,此时第iii位可以考虑从0∼90\sim90∼9除6以外的所有情况,此时一共有9种选择,而i−1i-1i−1位往后,无论选了一个6 ororor 两个6都可以向此状态转移。

其次,再考虑j=1j=1j=1与j=2j=2j=2的情况,此时就很显然第i−1i-1i−1位必须选一个或者两个,不过多赘述。

LastnottheleastLast\:\:not\:\:the\:\:leastLastnottheleast

F[i,3]F [i,3]F[i,3]的转移就不一样了,它又该分2种情况讨论:

首先,是三个6从第iii位开始往下排,此时应该显然由F[i−1,2]F [i-1,2]F[i−1,2]的方案数转移过来,
然后由于还要继承前i−1i-1i−1位的方案数,
又由于第iii位从0∼90\sim90∼9都可以选,且不会与之前重复,所以应该是10×F[i−1,3]10\times F[i-1,3]10×F[i−1,3]

至此,完成动态规划后,预处理就完成了,我们就可以开开心心,快快乐乐的进入下一步了。

2.2.2. 试填法 解决问题

至此我们从左到右依次考虑每一位,同时记录当前末尾已经有连续的几个6。
从小到大枚举当前数位填的数字,通过预处理的FFF数组来直接计算魔鬼数的个数,与XXX比较即可。

下面就是激动人心的上代码时间了!!!

part.3part.3part.3 CodeCodeCode

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
ll f[22][4];//
int T,x;
int main() {scanf("%d",&T);f[0][0]=1;for(int i=1; i<=20; i++) {//DP预处理f[i][0]=9*(f[i-1][0] + f[i-1][1] + f[i-1][2]);f[i][1]=f[i-1][0];f[i][2]=f[i-1][1];f[i][3]=f[i-1][2]+10*f[i-1][3];}while(T--) {int m=0;scanf("%d",&x);for(m=3; f[m][3]<x; m++);//枚举来确定第X个魔鬼数的位数m;int k=0;//k表示从i+1位向前有连续k个6;for(int i=m; i>=1; i--)for(int j=0; j<=9; j++) {ll cnt=f[i-1][3];//前i位且第i位为j时的总的方案数; if(j==6 || k==3)for(int l=max(3-k-(j==6),0); l<3; l++) cnt+=f[i-1][l];if(cnt<x)//如果cnt比x小,说明当前位的j小于答案,进行累积并进入下一层; x-=cnt;else {//否则,可确定j为当前的答案; if(k<3) {//当k大于三等于的时候后面无论怎样都是魔鬼数了,就不用考虑当前是否为6了,可以直接记录答案if(j==6)k++;elsek=0;}printf("%d",j);break;}}puts("");}
}

P.SP.SP.S

这是本蒟蒻的第一篇题解,写出来还是很激动的,看着这一篇完完整整的题解,很有成就感。谨以这一篇题解纪念我接近一年半的OIOIOI生涯吧。(估计考完就退役了)

还有最后7天就要参加CSP−SCSP-SCSP−S的比赛了,希望RP++!!!RP++!\:!\:!RP++!!!

数位DP———POJ 3208 启示录相关推荐

  1. #数位dp#poj 3208 Apocalypse Someday

    题目 定义一种神奇的数当且仅当数位上至少有3个6,问第n个神奇的数是多少 分析 那么可以预处理出由i位数字构成的魔鬼/非魔鬼数, f[i][0]=9∗(f[i−1][0]+f[i−1][1]+f[i− ...

  2. poj 3208 Apocalypse Someday 数位dp+二分答案

    Apocalypse Someday Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 2203   Accepted: 11 ...

  3. poj 3208 Apocalypse Someday(数位dp)

    题意:给定n,输出第n大包含666的数字. 分析:数位dp,详见<算法竞赛进阶指南>P342-344. 代码: #include<iostream> #include<c ...

  4. Poj 3208 Apocalypse Someday(数位dp + 二分)

    题目大意:   有三个连续的6在一起的数就是beast数,前几个beast数是:666,1666,2666,-   T组数据,每组询问排名为n的beast的数是什么? 解题思路 第一眼看到懵逼了,不是 ...

  5. poj3208启示录——数位DP

    题目:http://poj.org/problem?id=3208 数位DP,首先按位数预处理出每一种位数的情况,包括有多少个魔鬼数和有多少个以6开头的非魔鬼数,以便递推.累加等等: 然后先找出第X个 ...

  6. POJ 3252 数位DP

    链接: http://poj.org/problem?id=3252 题意: 给你一个区间l,r,求区间中有多少个数转化为二进制后1的个数大于等于0的个数 题解: 还是数位dp,不过多了前导0的判断 ...

  7. POJ - 3252 Round Numbers(数位dp)

    题目链接:点击查看 题目大意:规定一个数如果二进制中0的个数大于等于1的个数,则这个数称为"整数",问闭区间a,b中有多少个整数 题目分析:数位dp,dp[pos][c0][c1] ...

  8. Round Numbers POJ - 3252(数位dp+判断前导零)

    题意 求二进制表示中0的个数大于1的数的个数. 题目 The cows, as you know, have no fingers or thumbs and thus are unable to p ...

  9. POJ - 3252二进制数位DP

    给一个区间,让你求出区间内有多少个round numbers,所谓的round numbers就是二进制表示下,0的数量比1的数量多的数. 二进制数位DP,需要注意的地方: 1.前导0不算二进制表示下 ...

最新文章

  1. python环境下,执行系统命令方法
  2. HTML基础_Day01
  3. java读word_java读word文件(示例代码)
  4. 汇编语言:实验10 根据材料编程—1.显示字符串
  5. Bootstrap文件上传插件File Input的使用
  6. DIV CSS 网页兼容全搞定 (IE6 IE7 IE8 IE9 火狐 谷歌)
  7. 系统自带命令subst.exe创建虚拟软驱
  8. Office 2210 能打钩的复选框
  9. 机器学习算法原理与编程实践-郑捷著 读书笔记—第一章part1
  10. vhdl timing requirements not met 错误 quartusII中
  11. 2021-11-29 拿到第一个badger
  12. 负担过重何以轻装前行
  13. css系统自带字体_CSS系统字体堆栈参考
  14. 计算机管理找不到文件怎么办,Windows找不到文件怎么办
  15. 直播网站LiveTV Mining,爬虫抓取数据 python3+scrapy
  16. 做跨境必不可少的装备,虾扑erp帮东南亚卖家便捷跨境!
  17. 编写支持SSR的通用组件指南
  18. 关于sql语句,where,group by,having,order by 优先级的理解
  19. win10最流畅版本
  20. pwn——ciscn_2019_n_1#pwn1_sctf_2016#jarvisoj_level0

热门文章

  1. cmd中发送http请求_curl命令与HTTP请求
  2. Mac App Store下载总是发生错误如何解决?
  3. 机器学习 | 集成算法 | Bagging | Boosting | 概念向
  4. ModelArts实现语音分类、文字类别分类
  5. 基于Rsoft软件进行长周期光纤光栅模拟
  6. 【STM32F429】RT-Thread结合TouchGFX实战教程
  7. SAP入门 - 配置中文界面
  8. 低压配电网络中三相潮流计算的前推回代法(Matlab实现)
  9. 总结matlab2018a安装后遇到matlab license manager error -8
  10. 知识进步的阶梯--书