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)的主要内容,如果未能解决你的问题,请参考以下文章