#数位dp#poj 3208 Apocalypse Someday

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sugar_free_mint/article/details/82013062

题目

定义一种神奇的数当且仅当数位上至少有3个6,问第n个神奇的数是多少


分析

那么可以预处理出由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 ]

然后用试填法,求出答案


代码

#include <cstdio>
long long f[21][4];
int max(int a,int b){return a>b?a:b;}
int main(){
    f[0][0]=1;
    for (int i=0;i<20;i++){
        for (int j=0;j<3;j++)//动态规划
            f[i+1][j+1]+=f[i][j],
            f[i+1][0]+=f[i][j]*9;
        f[i+1][3]+=f[i][3]*10;
    }
    int t; scanf("%d",&t);
    while (t--){
        int n,m; scanf("%d",&n);
        for (m=3;f[m][3]<n;m++);//找到应该的位数
        for (int i=m,k=0;i;i--){
            for (int j=0;j<=9;j++){
                long long cnt=f[i-1][3];
                if (j==6||k==3)
                for (int l=max(3-k-(j==6),0);l<3;l++) cnt+=f[i-1][l];//可能性
                if (cnt<n) n-=cnt;//还没有求到
                else {
                if (k<3) if (j==6) k++; else k=0;
                putchar(j+48);//找到答案
                break;
                }
            }
        }
        putchar('\n');
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sugar_free_mint/article/details/82013062
今日推荐