zoukankan      html  css  js  c++  java
  • 【poj3208-Apocalypse Someday】数位DP

    题意:问你在所有包含666的数中,第n大的是多少。(1 ≤ n ≤ 50,000,000) 。开头几个是666, 1666, 2666, 3666, 4666, 5666…

    题解:

    这题可以用AC自动机,不知道这个怎么做。。

    用了数位DP。

    第一道自己好好调出来的数位DP。。哭泣

    (一)先用DP预处理出含有666的k位数一共有多少个,不含有666的k位数一共有多少个。只用求一边就可以,另一边用总数来减。

    然后for一遍,判断出第n大的是多少位数。

    //d[0][i] 第一位不是6的i位数不含666总方案数
    //d[1][i] 第一位是6...
    //d[2][i] 连续两个6...
    //d[3][i] 不含666的i位数的总方案数
    //d[4][i] 含有666的i位数...

    (二)填数(从左往右)。填的时候要记录前两位是什么。

    分两种情况:

    1.填的数中已经有666。则后面的位可以填有666和没有666的数。

    2.没有666。

    这个再分两种 (1)现在不要填6-->则后面必须有666

                      (2)现在填6  如果是xx6,则后面可以是66xxxx或含有666的数;如果是x66,则后面是6xxx或者66xxx或者含有666的数。如果是xx6,则后面是66xxx或者含有666的数。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<queue>
      6 using namespace std;
      7 
      8 typedef long long LL;
      9 const int N=50000010,D=10;
     10 LL d[5][20];
     11 int n,ans[20];
     12 //d[0][i] 第一位不是6的i位数不含666总方案数
     13 //d[1][i] 第一位是6...
     14 //d[2][i] 连续两个6...
     15 //d[3][i] 不含666的i位数的总方案数
     16 //d[4][i] 含有666的i位数...
     17 
     18 int main()
     19 {
     20     freopen("a.in","r",stdin);
     21     freopen("a.out","w",stdout);
     22     memset(d,0,sizeof(d));
     23     memset(ans,0,sizeof(ans));
     24     LL sum=100;
     25     d[0][1]=9;d[1][1]=1;d[2][1]=0;d[3][1]=10;d[4][1]=0;
     26     d[0][2]=9*10;d[1][2]=9;d[2][2]=1;d[3][2]=10*10;d[4][2]=0;
     27     for(int i=3;i<=D;i++)
     28     {
     29         d[0][i]=9*d[3][i-1];
     30         d[1][i]=d[0][i-1];
     31         d[2][i]=d[1][i-1];
     32         d[3][i]=d[0][i]+d[1][i]+d[2][i];
     33         sum*=10;
     34         d[4][i]=sum-d[3][i];
     35     }
     36     int T;
     37     scanf("%d",&T);
     38     while(T--)
     39     {
     40         scanf("%d",&n);
     41         int k=0;
     42         for(LL i=3;i<=D;i++)
     43             if(d[4][i]>n) {k=i;break;}
     44         int now=0,a=0,b=0;
     45         bool ok=0;
     46         for(int i=1;i<=k;i++)
     47         {
     48             if(i==k) 
     49             {
     50                 if(!ok) ans[k]=6;
     51                 else ans[k]=n-now-1;
     52                 break;
     53             }
     54             bool bk=0;
     55             for(int j=0;j<=9;j++)
     56             {
     57                 if(!ok)
     58                 {
     59                     if(j!=6)
     60                     {
     61                         if(now+d[4][k-i]<n) now+=d[4][k-i];
     62                         else ans[i]=j,bk=1;
     63                     }
     64                     else
     65                     {
     66                         if(a==6 && b==6) 
     67                         {
     68                             if(now+d[3][k-i]+d[4][k-i]<n) now+=d[3][k-i]+d[4][k-i];
     69                             else ans[i]=j,bk=1,ok=1;
     70                         }
     71                         else if(a!=6 && b==6)
     72                         {
     73                             if(now+d[1][k-i]+d[2][k-i]+d[4][k-i]<n) now+=d[1][k-i]+d[2][k-i]+d[4][k-i];
     74                             else ans[i]=j,bk=1;
     75                         }
     76                         else //这里原本打了a、b都不等于6,WA,应该是b不等于6就可以了。
     77                         {
     78                             if(now+d[2][k-i]+d[4][k-i]<n) now+=d[2][k-i]+d[4][k-i];
     79                             else ans[i]=j,bk=1;
     80                         }
     81                     }
     82                 }
     83                 else 
     84                 {
     85                     if(now+d[3][k-i]+d[4][k-i]<n) now+=d[3][k-i]+d[4][k-i];
     86                     else ans[i]=j,bk=1;
     87                 }
     88                 if(bk) break;
     89             }
     90             a=ans[i-1],b=ans[i];
     91         }
     92         bool fir=0;
     93         for(int i=1;i<=k;i++)
     94         {
     95             if(fir==0 && ans[i]==0) continue;
     96             if(fir==0 && ans[i]!=0) fir=1;
     97             if(fir) printf("%d",ans[i]);
     98         }
     99         if(T) printf("
    ");
    100     }
    101     return 0;
    102 }
  • 相关阅读:
    动态规划之最大子段和问题
    hdu1203 I NEED A OFFER!---概率DP(01背包)
    hdu1087 Super Jumping! Jumping! Jumping!---基础DP---递增子序列最大和
    hdu2062 Subset sequence----递推
    java线程基础巩固---通过实验分析This锁和Class锁的存在
    java8学习之BiFunction函数式接口实例演示&Predicate函数式接口详解
    java8学习之Function与BiFunction函数式接口详解
    java8学习之Lambda表达式继续探讨&Function接口详解
    java8学习之Lambda表达式深入与流初步
    java8学习之深入函数式接口与方法引用
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/5673525.html
Copyright © 2011-2022 走看看