Valley Numer
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 492 Accepted Submission(s): 259
Problem Description
众所周知,度度熊非常喜欢数字。
它最近发明了一种新的数字:Valley Number,像山谷一样的数字。
当一个数字,从左到右依次看过去数字没有出现先递增接着递减的“山峰”现象,就被称作 Valley Number。它可以递增,也可以递减,还可以先递减再递增。在递增或递减的过程中可以出现相等的情况。
比如,1,10,12,212,32122都是 Valley Number。
121,12331,21212则不是。
度度熊想知道不大于N的Valley Number数有多少。
注意,前导0是不合法的。
它最近发明了一种新的数字:Valley Number,像山谷一样的数字。
![](https://i-blog.csdnimg.cn/blog_migrate/c749efa055528c019be60f9ed46ffb07.jpeg)
当一个数字,从左到右依次看过去数字没有出现先递增接着递减的“山峰”现象,就被称作 Valley Number。它可以递增,也可以递减,还可以先递减再递增。在递增或递减的过程中可以出现相等的情况。
比如,1,10,12,212,32122都是 Valley Number。
121,12331,21212则不是。
度度熊想知道不大于N的Valley Number数有多少。
注意,前导0是不合法的。
Input
第一行为T,表示输入数据组数。
每组数据包含一个数N。
● 1≤T≤200
● 1≤length(N)≤100
每组数据包含一个数N。
● 1≤T≤200
● 1≤length(N)≤100
Output
对每组数据输出不大于N的Valley Number个数,结果对 1 000 000 007 取模。
Sample Input
3 3 14 120
Sample Output
3 14 119
Source
它不可以先增后减,所以我们需要有三种状态,一种是增状态,一种是减状态,一种是初始状态(或不增不减)
这三种状态分别用数字 3 2 4 表示,所以要不出现先减后增的话,就是不记录先3后2这种情况,其他的都记录下来。
DP[当前位][前一位数的值][当前状态]
一开始状态默认为 4 ,然后出现了非0数之后令它为 2 状态,因为可以先2后3,而不能先3后二,如果一开始就赋值3的话,单调递减的情况会被认为是不符合的,所以要设为2,然后接下来的每次都拿当前数字去和前一位数比较,判断它是增还是减,出了先增后减的情况以外,其他都计数就行了。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
#define ll long long
#define mod 1000000007
char num[200];
ll dp[150][15][5];
ll wei[150];
int len;
ll dfs(ll pos,ll pre,ll now,ll flag){
if(pos < 0){
if(now == 4)
return 0;
return 1;
}
if(!flag && dp[pos][pre][now] != -1)
return dp[pos][pre][now];
ll up = flag ? wei[pos] : 9;
ll sum = 0;
for(int i = 0;i <= up;i++){
if(now == 3 && pre <= i){
sum += dfs(pos - 1,i,now,flag && i == up) % mod;
sum %= mod;
}
if(now == 2){
if(pre >= i){
sum += dfs(pos - 1,i,now,flag && i == up) % mod;
sum %= mod;
}else{
sum += dfs(pos - 1,i,3,flag && i == up) % mod;
}
}
if(now == 4){
if(i == 0){
sum += dfs(pos - 1,i,now,flag && i == up) % mod;
sum %= mod;
}else{
sum += dfs(pos - 1,i,2,flag && i == up) % mod;
sum %= mod;
}
}
}
if(!flag)
dp[pos][pre][now] = sum;
return sum;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(dp,-1,sizeof(dp));
scanf("%s",num);
len = strlen(num);
reverse(num,num + len);
for(int i = 0;i < len;i++){
wei[i] = num[i] - '0';
}
ll ans = dfs(len - 1,0,4,1) % mod;
printf("%lld\n",ans);
}
return 0;
}