zoukankan      html  css  js  c++  java
  • POJ3208魔鬼数

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

    与一般的数位dp有点不同的是,没有给出上界,而是要通过值来判断这一位该填什么。

    当然是从高位向低位填。

    为了知道这一位填下去对答案有什么影响,需要预处理出后面无限制的魔鬼数个数。

    预处理魔鬼数最重要的是不重不漏。这一位的魔鬼数=上一位的所有魔鬼数+这一位填6带来的新魔鬼数。

    新魔鬼数不能与上一位已有的魔鬼数重复,所以需要记录“开头有2个6的魔鬼数”。

    为了得到这个,递推需要记录“开头有1个6的非魔鬼数”和“开头有0个6的非魔鬼数”。

    f [ i ][ 0 ]=9*f [ i-1 ][ 0 ]+9*f [ i-1 ][ 1 ]+9*f [ i-1 ][ 2 ];  //不填6

    f [ i ][ 1 ]=f [ i-1 ][ 0 ];  f [ i ][ 2 ]=f [ i-1 ][ 1 ];  f [ i ][ 3 ]=f [ i-1 ][ 2 ];  //填6

    代码中n-=cnt意思是这一位越过这个j之后,当前累计魔鬼数数量就多了cnt个。就像普通数位dp一样。

    看了蓝皮书上的精美写法!竟然可以用一句for给m赋值!l 的循环也写的很好!

    dp的初值是自己不熟的地方。

    别忘了输出当前位之后要break。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int LM=20;
    int n,m,k,t;
    long long f[LM+5][5];
    void pre()
    {
        f[0][0]=1;//
        for(int i=0;i<LM;i++)
        {
            for(int j=0;j<3;j++)
            {
                f[i+1][j+1]+=f[i][j];
                f[i+1][0]+=9*f[i][j];
            }
            f[i+1][3]+=10*f[i][3];
        }
    }
    int main()
    {
        pre();
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            k=0;
            for(m=0;f[m][3]<n;m++);
            for(int i=m;i;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];
        //            printf("i=%d j=%d cnt=%lld n=%d
    ",i,j,cnt,n);
                    if(cnt<n)n-=cnt;
                    else
                    {
                        if(k<3)
                        {
                            if(j==6)k++;
                            else k=0;
                        }
                        printf("%d",j);
        //                printf("i=%d j=%d
    ",i,j);
                        break;
                    }
                }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    n的阶乘
    只出现一次的数字
    2的幂次方
    海康摄像头调用程序
    对象和Map转化gongju
    base64和图片的相互转换
    三员管理的定义
    关于注解的理解
    vue开发环境和生产环境里面解决跨域的几种方法
    thymeleaf 入门
  • 原文地址:https://www.cnblogs.com/Narh/p/8660761.html
Copyright © 2011-2022 走看看