poj 3208 Apocalypse Someday (数位dp)


Apocalypse Someday

Time Limit: 1000MS   Memory Limit: 131072K
Total Submissions: 1490   Accepted: 686

Description

The number 666 is considered to be the occult “number of the beast” and is a well used number in all major apocalypse themed blockbuster movies. However the number 666 can’t always be used in the script so numbers such as 1666 are used instead. Let us call
the numbers containing at least three contiguous sixes beastly numbers. The first few beastly numbers are 666, 1666, 2666, 3666, 4666, 5666…

Given a 1-based index n, your program should return the nth beastly number.

Input

The first line contains the number of test cases T (T ≤ 1,000).

Each of the following T lines contains an integer n (1 ≤ n ≤ 50,000,000) as a test case.

Output

For each test case, your program should output the nth beastly number.

Sample Input

3
2
3
187

Sample Output

1666
2666
66666

Source

POJ Monthly--2007.03.04, Ikki, adapted from TCHS SRM 2 ApocalypseSomeday

题意:

找出第n个包含666的数字。

思路:

考虑数位,考虑当前位置,有三种状态,0表示没有6,1表示有6,2表示有66,3表示有666。

dp[i][j]表示第i位前缀状态为j时能得到包含666数字的方案数,那么枚举当前位置选多少来进行状态转移即可。

输出方案先找到位数(与dp[i][0]比较),然后逐位确定,状态也要逐位更新。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#include <sstream>
#define maxn 1005
#define MAXN 200005
#define mod 1000000007
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-4
typedef long long ll;
using namespace std;

ll n,m,k,ans,tot,cnt,flag;
ll dp[15][4],tran[4][10];

void presolve() // 预处理dp
{
    ll i,j,t;
    tran[0][6]=1,tran[1][6]=2,tran[2][6]=3;
    for(i=0;i<=9;i++) tran[3][i]=3;
    dp[0][3]=1;
    for(i=1;i<=12;i++)
    {
        for(j=0;j<=3;j++)
        {
            for(k=0;k<=9;k++)
            {
                dp[i][j]+=dp[i-1][tran[j][k]];
            }
        }
    }
}
void solve()
{
    ll i,j,st;
    for(i=1;i<=12;i++)  // 找到位数
    {
        if(dp[i][0]>=n){ tot=i; break; }
    }
    st=0;
    for(i=tot;i>=1;i--) // 逐位确定
    {
        for(j=0;j<=9;j++)
        {
            if(dp[i-1][tran[st][j]]>=n)
            {
                st=tran[st][j];
                printf("%d",j);
                break ;
            }
            n-=dp[i-1][tran[st][j]];
        }
    }
    puts("");
}
int main()
{
    ll i,j,t;
    presolve();
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld",&n);
        solve();
    }
    return 0;
}
时间: 2024-10-10 20:23:31

poj 3208 Apocalypse Someday (数位dp)的相关文章

POJ 3208 Apocalypse Someday(数位dp)

题意:输出第n个包含连续三个6的数 思路: dp[i][0]表示i位数中首位不为6且不含666的数的数量 dp[i][1]表示i位数中首位连续1个6并且不含666的数的数量 dp[i][2]表示i位数中首位连续2个6并且不含666的数的数量 dp[i][3]表示i位数中含有666的数的数量 写出递推关系即可,再确定出带求的数有多少位,再从高位到低位逐次确定 //132K 16MS #include<cstdio> #include<cstring> #include<algo

POJ 3689 Apocalypse Someday [数位DP]

Apocalypse Someday Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 1807   Accepted: 873 Description The number 666 is considered to be the occult “number of the beast” and is a well used number in all major apocalypse themed blockbuster

POJ 3208 Apocalypse Someday 二分答案+数位DP

这题应该是POJ最强大的一道数位DP了吧 正解是AC自动机 不会 还是写数位DP吧 题目大意:我们令含有666的数字为不吉利数字,则可以得到一个递增数列: {an}=666,1666,2666,3666,4666,5666,6660,6661,.... 给定n,求an 首先我们把这个问题转化成另一个问题:给定n,求1~n中有多少个数含有666 解决了这个问题,把原问题二分答案即可 首先预处理f数组,令 f[i][0]表示i位数中首位不为6且不含666的数的数量 f[i][1]表示i位数中首位连续

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

/** 题目:poj3208 Apocalypse Someday 链接:http://poj.org/problem?id=3208 题意:求第K(K <= 5*107)个有连续3个6的数. 思路:数位dp+二分. dp[i][j]表示长度为i,前缀状态为j时含有的个数. j=0表示含有前导0: j=1表示前缀连续1个6 j=2表示前缀连续2个6 j=3表示前缀连续3个6 j=4表示前缀不是6: */ //#include<bits/stdc++.h> #include<cstr

【POJ3208】传说中POJ最难的数位DP?(正解AC自动机,二解数位DP,吾异与之)

题意: 多组数据,每组求第n个包含'666'的数(不能断开),如1:666,2:1666,14:6667. 题解: AC自动机解法没去想,数位DP没学,这里有一种类似于数位DP,却又与数位DP不同,我称为数位树. 数位树: 将数n如线段树一样地拆分成多个小段,进行递归处理得出答案. 本题详(lue)解: 直接看每一位应该是什么数,然后n减去相应的数,使得在下一层转换为子问题"在开头有b个连续的6时,求第a个带'666'的数".就是如此简单,如此简单!!!! 代码来啦! #include

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

题目链接:[kuangbin带你飞]专题十五 数位DP E - Round Numbers 题意 给定区间.求转化为二进制后当中0比1多或相等的数字的个数. 思路 将数字转化为二进制进行数位dp,由于一个二进制数的最高位必须为1.所以设置变量first记录前面位是否有1,若有1,则可随意放,否则,仅仅可放1. 同一时候.上面的推断决定了搜索时len的大小与二进制本身的长度不一定相等,所以需两个变量对1和0的个数进行记录. 用dp[a][b][c]保存长度a,b个0,c个1的数字个数.记忆化搜索.

POJ 3252 Round Numbers (数位DP)

题意:求区间内一个数二进制位1的数量大于等于0的数的个数. 析:dp[i][j][k] 表示前 i 位,长度为 j 的,1的数量是 k.注意前导0. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <

POJ 3252 round numbers(数位DP)

#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> #include <vector> #include <queue> #include <cstring> #include <set> #include <stack> #include <m

poj 3252 Round Number 数位dp

Round Numbers Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 11481   Accepted: 4305 Description The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, Paper, Stone' (also known as 'Rock, Paper, Scissors',