HDU 6148 Valley Numer (数位DP)

Posted guapisolo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }

 




以上是关于HDU 6148 Valley Numer (数位DP)的主要内容,如果未能解决你的问题,请参考以下文章

hdu 6148 Valley Numer (数位dp)

HDU 6148 Valley Numer(数位DP)

HDU6148 Valley Numer

[HDOJ6148] Valley Numer(数位dp)

2017"百度之星"程序设计大赛 - 复赛1005&&HDU 6148 Valley Numer数位dp

HDU-6148 Valley Number (数位DP)