POJ3208:Apocalypse Someday
很神奇的一道题,正解是AC自动机+数位DP,个人感觉POPOQQQ大爷的方法更方便理解。
按照一般套路,先搞个DP预处理,设$f[i][0/1/2/3]$分别表示对于$i$位数,其中有多少个前0/1/2位为6的个数和整体中包含666的个数。那么就很容易得到以下转移方程。
$f[i][3]=f[i-1][3] \times 10+f[i-1][2]$
$f[i][2]=f[i-1][1]$
$f[i][1]=f[i-1][0]$
$f[i][0]=(f[i-1][0]+f[i-1][1]+f[i-1][2]) \times 9$
剩下的就比较麻烦了。
刚开始我想的是不断剔除排名从而确定每一位上的数。但是这个是很麻烦的,而且不好处理。更换一种方案就是通过二分确定这个排名的个数,只要我们能验证小于$N$的数中有多少个满足要求的数。
这个求的过程相当玄学...我也说不上来QAQ
//NOIp DP apo
//by Cydiater
//2016.10.4
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <ctime>
#include <iomanip>
#include <cmath>
using namespace std;
#define ll long long
#define up(i,j,n) for(ll i=j;i<=n;i++)
#define down(i,j,n) for(ll i=j;i>=n;i--)
#define FILE "apo"
const ll MAXN=1e6+5;
const ll oo=0x3f3f3f3f;
const ll mod=(1<<31)-1;
inline ll read(){
char ch=getchar();ll x=0,f=1;
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
ll f[25][10],leftt,rightt,mid,T;
namespace solution{
void pret(){
memset(f,0,sizeof(f));
f[0][0]=1;
up(i,1,21){
f[i][3]=f[i-1][3]*10+f[i-1][2];
f[i][2]=f[i-1][1];
f[i][1]=f[i-1][0];
f[i][0]=(f[i-1][0]+f[i-1][1]+f[i-1][2])*9;
}
}
ll check(ll num){
ll di=0,far=1,tmp=0,cnt=0,ans=0;
for(;far<num;far*=10,di++);
while(tmp<num){
ll re_cnt;
while(tmp+far<=num){
tmp+=far;
if(cnt==3) re_cnt=3;
else if((tmp/far)%10==7) re_cnt=cnt+1;
else re_cnt=0;
down(i,3,3-re_cnt)ans+=f[di][i];
}
if(cnt!=3)cnt=((tmp/far)%10==6?cnt+1:0);
di--;far/=10;
}
return ans;
}
ll slove(ll N){
leftt=1;rightt=100000000000000000LL;
N--;
while(leftt+1<rightt){
mid=(leftt+rightt)>>1;
ll tmp=check(mid);
if(tmp>N) rightt=mid;
else leftt=mid;
}
if(check(leftt)==N) return leftt;
return rightt;
}
}
int main(){
freopen(FILE".in","r",stdin);
//freopen(FILE".out","w",stdout);
using namespace solution;
pret();
T=read();
while(T--)cout<<slove(read())<<endl;
return 0;
}
POJ3208:Apocalypse Someday的更多相关文章
- 【POJ3208】Apocalypse Someday
Description 666号被认为是神秘的"野兽之数",在所有以启示录为主题的大片中都是一个被广泛使用的数字.但是,这个数字666不能总是在脚本中使用,所以应该使用1666这样 ...
- 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的数. ...
- POJ3208 Apocalypse Someday
题意 Language:Default Apocalypse Someday Time Limit: 1000MS Memory Limit: 131072K Total Submissions: 2 ...
- POJ 3689 Apocalypse Someday [数位DP]
Apocalypse Someday Time Limit: 1000MS Memory Limit: 131072K Total Submissions: 1807 Accepted: 87 ...
- Apocalypse Someday
Apocalypse Someday 定义一个数是合法的,当且仅当中间出现至少一个连续的大于三个的6,求第x个合法的数,\(x\leq 50,000,000\) 解 首先,注意到求第几个,即想到试填法 ...
- poj3208 Apocalypse Someday[数位DP]
数位中出现至少3个连续的'6'的数字(称魔鬼数),询问满足要求的排名k的数. 经典题型.采用试填法. 递推做法:预处理出$i$位数字中满足要求的数(下记为'魔鬼数').对每一位都从0到9试一遍,然而卡 ...
- POJ3208 Apocalypse Someday(二分 数位DP)
数位DP加二分 //数位dp,dfs记忆化搜索 #include<iostream> #include<cstdio> #include<cstring> usin ...
- POJ-3208 Apocalypse Someday (数位DP)
只要某数字的十进制表示中有三个6相邻,则该数字为魔鬼数,求第X小的魔鬼数\(X\le 5e7\) 这一类题目可以先用DP进行预处理,再基于拼凑思想,用"试填法"求出最终的答案 \( ...
- POJ 3208 Apocalypse Someday
题意: 将含有连续的三个6的数称为不吉利数,比如666,1666,6662,但是6266吉利.则666为第一个不吉利数,输入整数n,求第n个不吉利数.(n <= 5*10^7) 解法: 如果是给 ...
随机推荐
- Retro 2013
现在的team里每个迭代都会做一次retro,回顾这两周的情况,有哪些做得好的地方,有哪些做得不足的地方,并制定出一系列action,以期望在下一个迭代中解决这些问题.我觉得这种形式挺不错.因此今年的 ...
- 将IList转换为List
简单点说,IList<T>直接转换为List<T>可以不用考虑.IList<T>可以用至少2种方式简单的复制成List<T>:1.IList<T ...
- 【转】XSD (xml Schema Definition)
来自:http://www.cnblogs.com/newsouls/archive/2011/10/28/2227765.html Xml Schema的用途 1. 定义一个Xml文档中都有什么元 ...
- hdu-1823 Luck and Love
题目链接:hdu1823二维线段树单点更新区间查询 题意 向一个100*1000的二维空间中插入点,每次查询时,查询区间最大值. 题解 身高既然是100~200,那就相当于100;活泼度相当于1000 ...
- Rest API 开发 学习笔记(转)
Rest API 开发 学习笔记 概述 REST 从资源的角度来观察整个网络,分布在各处的资源由URI确定,而客户端的应用通过URI来获取资源的表示方式.获得这些表徵致使这些应用程序转变了其状态.随着 ...
- go-- 用go-mssql驱动连接sqlserver数据库
import _ "github.com/denisenkom/go-mssqldb" import ( "crypto/cipher" "crypt ...
- java多态实现原理
众所周知,多态是面向对象编程语言的重要特性,它允许基类的指针或引用指向派生类的对象,而在具体访问时实现方法的动态绑定.C++ 和 Java 作为当前最为流行的两种面向对象编程语言,其内部对于多态的支持 ...
- canvas拖动
var canvas=document.getElementById("canvas"); var cxt=canvas.getContext("2d"); v ...
- 开发错误记录七: Failed to create JVM:error code -4
今天启动Android studio 直接报如下错误: 用 java -verion 发现并不是环境变量没配置好,而是系统分配的内存,没有达到,as 的要求一种是:重启电脑,再启动 就ok 二种是 重 ...
- 标题栏ToolBar
使用标题栏ToolBar 首先需要在AndroidManifest.xml中修改 application主题或者activity主题 隐藏原生标题栏 在styles.xml中自定义主题 a ...