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<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;

ll dp[15][4];
const int trans[4][10]={
    {0,0,0,0,0,0,0,0,0,0},
    {3,3,3,3,3,3,0,3,3,3},
    {3,3,3,3,3,3,1,3,3,3},
    {3,3,3,3,3,3,2,3,3,3}
};
int main(){
    dp[0][0]=1;
    for(int i=1;i<=15;i++){
        dp[i][0]=(dp[i-1][0]+dp[i-1][1]+dp[i-1][2])*9;
        dp[i][1]=dp[i-1][0];
        dp[i][2]=dp[i-1][1];
        dp[i][3]=dp[i-1][3]*10+dp[i-1][2];
    }
    int T;
    scanf("%d",&T);
    while(T--){
        ll n;
        scanf("%I64d",&n);
        int dig=0;
        int cur=3;
        while(dp[dig][3]<n) dig++;
        while(dig){
            ll s=0;
            for(int i=0;i<10;i++){
                ll tmps=0;
                for(int j=3;j>=trans[cur][i];j--){
                    tmps+=dp[dig-1][j];
                }
                if(s+tmps>=n){
                    printf("%d",i);
                    cur=trans[cur][i];
                    break;
                }
                s+=tmps;
            }
            n-=s;
            dig--;
        }
        putchar('\n');
    }
    return 0;
}
时间: 2024-10-29 10:46:41

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

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位数中首位连续

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 blockb

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',