题目:http://poj.org/problem?id=3208

与一般的数位dp有点不同的是,没有给出上界,而是要通过值来判断这一位该填什么。

当然是从高位向低位填。

为了知道这一位填下去对答案有什么影响,需要预处理出后面无限制的魔鬼数个数。

预处理魔鬼数最重要的是不重不漏。这一位的魔鬼数=上一位的所有魔鬼数+这一位填6带来的新魔鬼数。

新魔鬼数不能与上一位已有的魔鬼数重复,所以需要记录“开头有2个6的魔鬼数”。

为了得到这个,递推需要记录“开头有1个6的非魔鬼数”和“开头有0个6的非魔鬼数”。

f [ i ][ 0 ]=9*f [ i-1 ][ 0 ]+9*f [ i-1 ][ 1 ]+9*f [ i-1 ][ 2 ];  //不填6

f [ i ][ 1 ]=f [ i-1 ][ 0 ];  f [ i ][ 2 ]=f [ i-1 ][ 1 ];  f [ i ][ 3 ]=f [ i-1 ][ 2 ];  //填6

代码中n-=cnt意思是这一位越过这个j之后,当前累计魔鬼数数量就多了cnt个。就像普通数位dp一样。

看了蓝皮书上的精美写法!竟然可以用一句for给m赋值!l 的循环也写的很好!

dp的初值是自己不熟的地方。

别忘了输出当前位之后要break。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int LM=;
int n,m,k,t;
long long f[LM+][];
void pre()
{
f[][]=;//
for(int i=;i<LM;i++)
{
for(int j=;j<;j++)
{
f[i+][j+]+=f[i][j];
f[i+][]+=*f[i][j];
}
f[i+][]+=*f[i][];
}
}
int main()
{
pre();
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
k=;
for(m=;f[m][]<n;m++);
for(int i=m;i;i--)//i
for(int j=;j<=;j++)
{
long long cnt=f[i-][];
if(j==||k==)
for(int l=max(-k-(j==),);l<;l++)
cnt+=f[i-][l];
// printf("i=%d j=%d cnt=%lld n=%d\n",i,j,cnt,n);
if(cnt<n)n-=cnt;
else
{
if(k<)
{
if(j==)k++;
else k=;
}
printf("%d",j);
// printf("i=%d j=%d\n",i,j);
break;
}
}
printf("\n");
}
return ;
}

POJ3208魔鬼数的更多相关文章

  1. POJ3208 Apocalypse Someday

    题意 Language:Default Apocalypse Someday Time Limit: 1000MS Memory Limit: 131072K Total Submissions: 2 ...

  2. poj3208启示录——数位DP

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

  3. poj3208 Apocalypse Someday[数位DP]

    数位中出现至少3个连续的'6'的数字(称魔鬼数),询问满足要求的排名k的数. 经典题型.采用试填法. 递推做法:预处理出$i$位数字中满足要求的数(下记为'魔鬼数').对每一位都从0到9试一遍,然而卡 ...

  4. $Poj3208$ 启示录 数位统计$DP$

    Poj  AcWing Description Sol  这题长得就比较像数位$DP$叭. 所以先用$DP$进行预处理,再基于拼凑思想,通过"试填法"求出最终的答案. 设$F[i] ...

  5. POJ-3208 Apocalypse Someday (数位DP)

    只要某数字的十进制表示中有三个6相邻,则该数字为魔鬼数,求第X小的魔鬼数\(X\le 5e7\) 这一类题目可以先用DP进行预处理,再基于拼凑思想,用"试填法"求出最终的答案 \( ...

  6. 0x5C 数位统计DP

    怎么说,数位DP还是我的噩梦啊,细节太恐怖了. 但是这章感觉又和之前的学的数位DP有差异?(应该是用DP预处理降低时间复杂度,好劲啊,不过以前都是记忆化搜索的应该不会差多少) poj3208 f[i] ...

  7. c语言宏定义#define的理解与资料整理

    1. 利用define来定义 数值宏常量 #define 宏定义是个演技非常高超的替身演员,但也会经常耍大牌的,所以我们用它要慎之又慎.它可以出现在代码的任何地方,从本行宏定义开始,以后的代码就就都认 ...

  8. C语言深度剖析---预处理(define)(转载)

    1.数值宏常量     #define宏定义是个演技非常高超的替身演员,但也会耍大牌的,所以我们使用它要慎之又慎.它可以出现在代码的任何地方,从本行宏定义开始,以后的代码都认识宏了:也可以把任何东西都 ...

  9. 数位DP -启示录

    http://poj.org/problem?id=3208 一个魔鬼数为包含连续三个666的的数字,给个n(n<5e7)求第n个魔鬼数. 预处理f[i][j],f[i][3]表示由前i位数字构 ...

随机推荐

  1. 计时(.NET)

    using System.Diagnostics; // 开始计时 Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); // 要计时的操 ...

  2. JavaScript 对象的使用

    JavaScript支持面向对象的编程方法. 2.9.1 window对象(窗口对象)的常用方法 内部函数 alert ( ) ,实际上是 window 对象的方法,写成全称为 window . al ...

  3. 学习浏览器缓存(http缓存)

    Q: 浏览器缓存是个什么东东,为什么要学习浏览器缓存涅? A: 浏览器缓存其实就是浏览器保存通过HTTP获取的所有资源,是浏览器将网络资源存储在本地的一种行为.浏览器缓存可以减少冗余数据的传输,减小服 ...

  4. React-Router v4.0 hashRouter使用js跳转

    React-Router v4.0上已经不推荐使用hashRouter,主推browserRouter,但是因为使用browserRouter需要服务端配合可能造成不便,有时还是需要用到hashRou ...

  5. vue-router如何做历史返回提示?

    获取vue-router的上一个页面是否存在或者是否是自己需要返回的地址,可以使用vue-router的的声明周期函数,有三种模式: 第一种.使用全局函数beforeEach,直接来获取form.pa ...

  6. 返回书签 GotoBookmark

    property Bookmark: TBookmark read GetBookmark write GotoBookmark; 直接给Bookmark属性赋值,还是 调用数据集GotoBookma ...

  7. 去除 DBGridEh SelectedRows里无效的书签

    数据集处于过滤状态,然后选中几个记录,再修改了这些记录中的某个字段(和过滤条件有关),导致那几个记录不符合过滤条件,不显示了.但是SelectedRows里 还保存着.如果不删除SelectedRow ...

  8. Struts2内置校验器——完整实例代码

    一.校验器的配置风格 1.字段校验器: <field name="被校验的字段"> <field-validator type="校验器名"& ...

  9. 高版本的jdk编译过的项目移到低版本的JDK的eclipse中出错的问题

    由于2台电脑安装的jdk版本不一样,导致从一台电脑移动项目到另一台电脑上时,运行出现了错误,错误信息如下: 主要是原先项目运行的JDK版本为1.8, 而要移过去的电脑的jdk是1.7的,首先已经把bu ...

  10. 冷知识:excel 2013有多少行列

    XFD1048576 列:24*26*26+6*26+4=16384 行:2^20=1048576