zoukankan      html  css  js  c++  java
  • 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 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

    题意:给定一个数字串A,不含前导0,长为m。m<=9求第P小的包含666的数字 P<=109

    课件上是个加强版:

    给定一个数字串A,不含前导0,长为m。m<=9
    求第P小的包含子串A的数字
    P<=109

    做法:

    二分答案X,转为判断小于等于X的包含子串A的数字有多少个
    F[i][j][k][l]表示,填完前i位,KMP指针指向A的第j位,之前是否出现过子串A的状态为k(0/1),下一位能否任意填数的状态为l(0/1),的方案数

    这里也可以用类似的做法二分答案

    或者可以不二分答案,因为答案是多少位可以判断出来,直接数位DP行了

    d[i][0]表示i位数中首位不为6且不含666的数的数量
    d[i][1]表示i位数中首位连续1个6并且不含666的数的数量
    d[i][2]表示i位数中首位连续2个6并且不含666的数的数量
    d[i][3]表示i位数中含有666的数的数量

    然后依次从小到大判断每一位填什么行了,记录sum为当前含666的数字的个数,six为当前需要几个6

    特判真的好麻烦,于是借鉴 http://blog.csdn.net/keshuai19940722/article/details/41087343 使用g[i][j]表示当前需要i个6,填了数字j后还需要几个6

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=12;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int g[4][12] = {
        {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 d[N][4];
    void dp(){
        d[0][0]=1;
        for(int i=1;i<=10;i++){
            d[i][0]=(d[i-1][0]+d[i-1][1]+d[i-1][2])*9;
            d[i][1]=d[i-1][0];
            d[i][2]=d[i-1][1];
            d[i][3]=d[i-1][3]*10+d[i-1][2];
            //printf("d %d %d
    ",i,d[i][3]);
        }
    }
    int n;
    int main(){
        //freopen("in.txt","r",stdin);
        dp();
        int T=read();
        while(T--){
            n=read();
            int dit=0,six=3,sum=0;
            while(d[dit][3]<n) dit++;
            //printf("dit %d
    ",dit);
            while(dit){//printf("hidit %d %d
    ",dit,sum);
                for(int i=0;i<=9;i++){
                    int _=0;
                    for(int j=3;j>=g[six][i];j--) _+=d[dit-1][j];
                    //printf("_ %d %d %d
    ",_,sum,six);
                    if(sum+_>=n){
                        printf("%d",i);
                        six=g[six][i];
                        break;
                    }
                    sum+=_;
                }
                dit--;
            }
            putchar('
    ');
        }
    }
     
     
  • 相关阅读:
    java代理的深入浅出(一)-Proxy
    事件分发模型的设计与实现
    LibProject使用theme无效。
    HeaderGridView
    android开源代码
    IOS学习4
    IOS学习3
    IOS学习2
    Mac上添加adb_usb.ini
    OC学习-1
  • 原文地址:https://www.cnblogs.com/candy99/p/6366380.html
Copyright © 2011-2022 走看看