只要某数字的十进制表示中有三个6相邻,则该数字为魔鬼数,求第X小的魔鬼数\(X\le 5e7\)

这一类题目可以先用DP进行预处理,再基于拼凑思想,用“试填法"求出最终的答案

\(F[i,3]\)表示由 \(i\) 位数字构成的魔鬼数有多少个,\(F[i,j](0\le j\le 2)\) 表示由 \(i\) 位数字构成的,开头已经有连续 \(j\) 个6的非魔鬼数有多少个。(允许前导0的存在,想一想为什么)

转移方程

  1. \(F[i,0] = 9*(F[i-1,0] + F[i-1,1] + F[i-1,2])\)
  2. \(F[i,1] = F[i-1,0]\)
  3. \(F[i,2] = F[i-1,1]\)
  4. \(F[i,3] = F[i-1,2] + 10 * F[i-1,3]\)

然后一位一位的试填,要注意前面填过的数字结尾如果有 k 个6,通过后面拼接 3-k 个6也可以构成魔鬼数

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
ll f[21][4];
int T,n,l;
void init(){
f[0][0] = 1;
for(int i=1;i<=20;i++){
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];
}
}
int main(){
init();
scanf("%d",&T);
while(T--){
scanf("%d",&n);
//l为答案的长度
for(l=3;f[l][3] < n;l++);
//k表示填过的数字末尾有k个6
for(int i=l,k=0;i;i--){
for(int j=0;j<=9;j++){
ll cnt = f[i-1][3];//后面预处理出的魔鬼数
//找能够拼凑出来的魔鬼数
if(j == 6 || k == 3){
if(k == 3){
for(int x = 0;x < 3;x++)
cnt += f[i-1][x];
}else{
for(int x = max(3-k-1, 0);x<3;x++){
cnt += f[i-1][x];
}
}
}
if(cnt < n) n -= cnt;
else{
if(k < 3) j == 6 ? k ++ : k=0;
printf("%d",j);break;
}
}
}
cout<<endl;
}
return 0;
}

POJ-3208 Apocalypse Someday (数位DP)的更多相关文章

  1. POJ 3689 Apocalypse Someday [数位DP]

    Apocalypse Someday Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 1807   Accepted: 87 ...

  2. poj3208 Apocalypse Someday 数位dp+二分 求第K(K <= 5*107)个有连续3个6的数。

    /** 题目:poj3208 Apocalypse Someday 链接:http://poj.org/problem?id=3208 题意:求第K(K <= 5*107)个有连续3个6的数. ...

  3. POJ 3208 Apocalypse Someday

    题意: 将含有连续的三个6的数称为不吉利数,比如666,1666,6662,但是6266吉利.则666为第一个不吉利数,输入整数n,求第n个不吉利数.(n <= 5*10^7) 解法: 如果是给 ...

  4. poj3208 Apocalypse Someday[数位DP]

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

  5. poj 3252 Round Numbers 数位dp

    题目链接 找一个范围内二进制中0的个数大于等于1的个数的数的数量.基础的数位dp #include<bits/stdc++.h> using namespace std; #define ...

  6. poj 3252 Round Numbers(数位dp 处理前导零)

    Description The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, P ...

  7. POJ 3252 Round Numbers(数位dp&amp;记忆化搜索)

    题目链接:[kuangbin带你飞]专题十五 数位DP E - Round Numbers 题意 给定区间.求转化为二进制后当中0比1多或相等的数字的个数. 思路 将数字转化为二进制进行数位dp,由于 ...

  8. $POJ$3252 $Round\ Numbers$ 数位$dp$

    正解:数位$dp$ 解题报告: 传送门$w$ 沉迷写博客,,,不想做题,,,$QAQ$口胡一时爽一直口胡一直爽$QAQ$ 先港下题目大意嗷$QwQ$大概就说,给定区间$[l,r]$,求区间内满足二进制 ...

  9. POJ 3208-Apocalypse Someday(数位dp)

    题意:给定n,输出第n大包含666的数字. 分析:dp[i][j][k][l]表示 长度为i,当前位是否是6,前一位是否6,是否已经包含666,表示的数量,再用二分找出第n大的这样的数字. #incl ...

  10. POJ - 3252 - Round Numbers(数位DP)

    链接: https://vjudge.net/problem/POJ-3252 题意: The cows, as you know, have no fingers or thumbs and thu ...

随机推荐

  1. vue中添加文字或图片水印

    首先引用warterMark.js,内容如下 'use strict' var watermark = (className,str,type) => { let dom = document. ...

  2. LInux维护一:VirtualMachine磁盘扩容

  3. 跨域的几种方式以及call(),apply() bind()方法的作用和区别

    jsonp: jsonp 全称是JSON with Padding,是为了解决跨域请求资源而产生的解决方案,是一种依靠开发人员创造出的一种非官方跨域数据交互协议. 一个是描述信息的格式,一个是信息传递 ...

  4. linux常用命令--转载

    转载自: https://www.cnblogs.com/Qsunshine/p/10402179.html 常用指令 ls 显示文件或目录 -l列出文件详细信息l(list) -a列出当前目录下所有 ...

  5. 【Oracle】更改oracle中的用户名称

    修改oracle中的用户名,要需要修改oracle基表中的相关内容, 1.查看user#, select user#,name from user$ s where s.name='用户修改前的'; ...

  6. 利用Numpy求解投资内部收益率IRR

    一. 内部收益率和净现值 内部收益率(Internal Rate of Return, IRR)其实要和净现值(Net Present Value, NPV)结合起来讲.净现值指的是某个投资项目给公司 ...

  7. LeetCode637. 二叉树的层平均值

    题目 1 class Solution { 2 public: 3 vector<double>ans; 4 vector<double> averageOfLevels(Tr ...

  8. ctfhub技能树—sql注入—整数型注入

    打开靶机 查看页面信息 查看回显位 查询数据库名 查询表名 查询字段 查询字段信息 使用sqlmap食用效果更佳 查数据库名 python2 sqlmap.py -u http://challenge ...

  9. SAP GUI用颜色区分不同的系统

    对于经常打开多个窗口的SAP用户,有时候可能同时登录了生产机.测试机和开发机,为了避免误操作,比如在测试要执行的操作,结果在生产机做了,结果可想而知. 虽然可以通过右下角查看再去判断,但是总是没有通过 ...

  10. Azure Terraform(六)Common Module

    一,引言 之前我们在使用 Terraform 构筑一下 Azure 云资源的时候,直接将所以需要创建的资源全面写在 main.tf 这个文件中,这样写主要是为了演示使用,但是在实际的 Terrafor ...