zoukankan      html  css  js  c++  java
  • HDU 6148 Valley Numer (数位DP)

    题目大意:当一个数字,从左到右依次看过去数字没有出现先递增接着递减的“山峰”现象,就被称作 Valley Number。它可以递增,也可以递减,还可以先递减再

    递增。在递增或递减的过程中可以出现相等的情况。

    比如,1,10,12,212,32122都是 Valley Number。

    121,12331,21212则不是。

    LJJ想知道不大于N的Valley Number数有多少。

    注意,前导0是不合法的。

    这道题前导0的情况非常好处理,遍历每一位都新生成一个1~9就行了

    定义$f[i][j][0/1][0/1]$表示第$i$位,最后一位是$j$,是否达到上界,前一段是否递增

    然后分情况讨论就行了

    由于直接讨论十分复杂,可以按每一维进行讨论

    先讨论是否递增,然后讨论是否达到上限

    然后把讨论的$DP$按乘法原理"合并"一下就行了

    这算是一个技巧吧

    我竟然1A了

     1 #include <cmath>
     2 #include <queue>
     3 #include <vector>
     4 #include <cstdio>
     5 #include <cstring>
     6 #include <algorithm>
     7 #define N1 121
     8 #define N2 4201
     9 #define M1 120
    10 #define ll long long
    11 #define dd double  
    12 #define uint unsigned int
    13 #define idx(X) (X-'0')
    14 #define mod 1000000007
    15 using namespace std;
    16 
    17 int gint()
    18 {
    19     int ret=0,fh=1;char c=getchar();
    20     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
    21     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
    22     return ret*fh;
    23 }
    24 int T,n;
    25 char str[N1];
    26 int a[N1];
    27 uint f[N1][10][2][2];
    28 
    29 int main()
    30 {
    31     //freopen("t1.in","r",stdin);
    32     scanf("%d",&T);
    33     while(T--)
    34     {   
    35     
    36     scanf("%s",str+1);
    37     n=strlen(str+1);
    38     for(int i=1;i<=n;i++)
    39         a[i]=idx(str[i]);
    40     memset(f,0,sizeof(f));
    41     for(int i=1;i<a[1];i++)
    42         f[1][i][0][0]=1;
    43     f[1][a[1]][1][0]=1;
    44     for(int i=1;i<n;i++)
    45     {
    46         for(int j=0;j<=9;j++)
    47         { //nolimit
    48             for(int k=0;k<j;k++) //down
    49             {
    50                 (f[i+1][k][0][0]+=f[i][j][0][0])%=mod;
    51                 if(k<a[i+1]) 
    52                     (f[i+1][k][0][0]+=f[i][j][1][0])%=mod;
    53                 else if(k==a[i+1]) 
    54                     (f[i+1][k][1][0]+=f[i][j][1][0])%=mod;
    55             }
    56             //plain
    57             (f[i+1][j][0][0]+=f[i][j][0][0])%=mod;
    58             (f[i+1][j][0][1]+=f[i][j][0][1])%=mod;
    59             if(j<a[i+1]){
    60                 (f[i+1][j][0][0]+=f[i][j][1][0])%=mod;
    61                 (f[i+1][j][0][1]+=f[i][j][1][1])%=mod;
    62             }else if(j==a[i+1]){
    63                 (f[i+1][j][1][0]+=f[i][j][1][0])%=mod;
    64                 (f[i+1][j][1][1]+=f[i][j][1][1])%=mod;
    65             }
    66             //up
    67             for(int k=j+1;k<=9;k++) 
    68             {
    69                 (f[i+1][k][0][1]+=f[i][j][0][0])%=mod;
    70                 (f[i+1][k][0][1]+=f[i][j][0][1])%=mod;
    71                 if(k<a[i+1]){
    72                     (f[i+1][k][0][1]+=f[i][j][1][0])%=mod;
    73                     (f[i+1][k][0][1]+=f[i][j][1][1])%=mod;
    74                 }else if(k==a[i+1]){
    75                     (f[i+1][k][1][1]+=f[i][j][1][0])%=mod;
    76                     (f[i+1][k][1][1]+=f[i][j][1][1])%=mod;
    77                 }
    78             }
    79         }
    80         for(int j=1;j<=9;j++)
    81             (f[i+1][j][0][0]+=1)%=mod;
    82     }
    83     uint ans=0;
    84     for(int k=0;k<=9;k++)
    85     {
    86         (ans+=f[n][k][0][0]+f[n][k][0][1])%=mod;
    87         (ans+=f[n][k][1][0]+f[n][k][1][1])%=mod;
    88     }
    89     printf("%u
    ",ans);
    90     
    91     }
    92     return 0;
    93 }




  • 相关阅读:
    MTU 理解和遇到的一些问题
    tm使用
    C++字符串中转义符
    安卓系统修改host文件简单教程
    公有继承的一个理解
    模板打印函数
    linux 设置时区
    ACE中的inline
    SecureCRT中脚本进行交互,发送Ctrl+C
    C++中多态的实现原理
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10034438.html
Copyright © 2011-2022 走看看