zoukankan      html  css  js  c++  java
  • poj3208启示录——数位DP

    题目:http://poj.org/problem?id=3208

    数位DP,首先按位数预处理出每一种位数的情况,包括有多少个魔鬼数和有多少个以6开头的非魔鬼数,以便递推、累加等等;

    然后先找出第X个魔鬼数的位数,再一位一位从0开始填数;

    写法有些技巧,详见代码及注释。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int t,x,f[25][4];
    void cl()
    {
    /*
    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;
    */
        f[0][0]=1;//!
        for(int i=0;i<20;i++)
        {
            for(int j=0;j<=2;j++)
            {
                f[i+1][j+1]+=f[i][j];
                f[i+1][0]+=f[i][j]*9;
            }
            f[i+1][3]+=10*f[i][3];
        }
    }
    int main()
    {
        scanf("%d",&t);
        cl();
        while(t--)
        {
            scanf("%d",&x);
            int m;//!
            for(m=3;f[m][3]<x;m++);//位数 ——实际总比f记录的多 
            for(int i=m,k=0;i>=1;i--)//所有魔鬼数数量累计 ,k表示末尾已经有k个6 
                for(int j=0;j<=9;j++)
                {
                    long long cnt=f[i-1][3];
                    if(j==6||k==3)//另外加 
                        for(int l=max(0,3-k-(j==6));l<3;l++)//l为加上的最小限制 
                            cnt+=f[i-1][l];
                    if(cnt<x)//则第i位应填更大的数;
                    {
                        x-=cnt;//j+1,减去上一层的魔鬼数数量 
                        continue;
                    }
                    else//本位填j,再缩小范围 
                    {
                        if(k<3&&j==6)k++;
                        if(k<3&&j!=6)k=0;//k=3意为本身已经是魔鬼数,不再改变 
                        printf("%d",j);//第i位填了j 
                        break;
                    }
                }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    PL/SQL详细介绍
    Linux服务器性能评估(转)
    oracle命令(转)
    Makefile介绍(转)
    delphi 指针
    浏览器的工作原理(转)
    高性能分布式计算与存储系统设计概要(上)(转)
    HTTP协议详解(转)
    MySQL性能优化(转)
    redhat 6.2安装telnet服务
  • 原文地址:https://www.cnblogs.com/Zinn/p/8660748.html
Copyright © 2011-2022 走看看