Problem Description
众所周知,度度熊非常喜欢数字。
它最近发明了一种新的数字:Valley Number,像山谷一样的数字。
当一个数字,从左到右依次看过去数字没有出现先递增接着递减的“山峰”现象,就被称作 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
Output
对每组数据输出不大于N的Valley Number个数,结果对 1 000 000 007 取模。
Sample Input
3
3
14
120
Sample Output
3
14
119
很裸的一个数位DP,第一个切的就是这题。。
但是我还是只会写深搜版本啊,正统DP版不会。。但是深搜好写的
#include<cstdio>
#include<cstring>
typedef long long LL;
const int MOD=1000000007;
char ss[105];
LL yy[105][3][3][3][15];
int n;
LL dfs (int now,bool a,bool b,bool c,int last)
//当前到第几位 是否出现了小 是否已经是递增 是否已经有第一个非0位 上一个是什么
{
if (now>n) return 1;
if (yy[now][a][b][c][last]!=-1) return yy[now][a][b][c][last];
int lalal=ss[now]-'0';//这一位是什么
LL ans=0;
if (c==false)//前面都是0
{
if (now==1)//还是第一位,不可以乱填
{
ans=ans+dfs(now+1,true,false,false,0);
ans%=MOD;
for (int u=1;u<lalal;u++)
{
ans=ans+dfs(now+1,true,false,true,u);
ans%=MOD;
}
ans=ans+dfs(now+1,false,false,true,lalal);
ans%=MOD;
}
else//也就是我爱填什么填什么
{
ans=ans+dfs(now+1,true,false,false,0);
ans%=MOD;
for (int u=1;u<=9;u++)
{
ans=ans+dfs(now+1,true,false,true,u);
ans%=MOD;
}
}
}
else
{
if (a==false)//不可以越界
{
if (b==false)//还不是递增
{
ans=ans+dfs(now+1,false,last<lalal,c,lalal);//我们这一位先填一样的
ans%=MOD;
if (lalal>last)
{
for (int u=0;u<=last;u++)
{
ans=ans+dfs(now+1,true,false,c,u);
ans%=MOD;
}
for (int u=last+1;u<lalal;u++)
{
ans=ans+dfs(now+1,true,true,c,u);
ans%=MOD;
}
}
else
for (int u=0;u<lalal;u++)
{
ans=ans+dfs(now+1,true,false,c,u);
ans%=MOD;
}
}
else//已经是递增了,不可以减了
{
for (int u=last;u<lalal;u++)//我要填什么
{
ans=ans+dfs(now+1,true,true,c,u);
ans%=MOD;
}
if (lalal>=last)
{
ans=ans+dfs(now+1,false,true,c,lalal);
ans%=MOD;
}
}
}
else//已经可以越界了
{
if (b==false)//目前还不是递增状态
{
for (int u=0;u<=9;u++)//填什么
{
ans=ans+dfs(now+1,true,last<u,c,u);
ans%=MOD;
}
}
else//已经是递增
{
for (int u=last;u<=9;u++)
{
ans=ans+dfs(now+1,true,true,c,u);
ans%=MOD;
}
}
}
}
yy[now][a][b][c][last]=ans;
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
memset(yy,-1,sizeof(yy));
scanf("%s",ss+1);
n=strlen(ss+1);
printf("%d\n",(dfs(1,false,false,false,0)%MOD-1+MOD)%MOD);
}
return 0;
}