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 然而写挂了很多次QAQ
f【i】【j】【k】【l】
表示考虑到第i位 这一位为j 此时是否开始上升 以及前l-1为是否和n(原数)相等
转移过程看代码吧QAQ 比较难讲 自己研究研究咯
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int mod=1e9+7,M=157; int read(){ int ans=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();} return ans*f; } int T,len,ans,h[M],f[M][15][2][2]; char s[M]; int calculate(int k){ memset(f,0,sizeof(f)); f[0][9][0][1]=1; for(int i=1;i<=k;i++){ int now=s[i]-'0'; for(int x=0;x<=9;x++){ for(int y=(i==1)?1:0;y<=9;y++){ for(int z=0;z<2;z++){ if(z&&y>now) continue; int nowf=(z&&y==now); if(x>=y){ if(x==y) f[i][y][1][nowf]=(f[i][y][1][nowf]+f[i-1][x][1][z])%mod; f[i][y][0][nowf]=(f[i][y][0][nowf]+f[i-1][x][0][z])%mod; } else{ f[i][y][1][nowf]=(f[i][y][1][nowf]+f[i-1][x][1][z])%mod; f[i][y][1][nowf]=(f[i][y][1][nowf]+f[i-1][x][0][z])%mod; } } } } } int sum=0; for(int x=0;x<=9;x++) for(int y=0;y<2;y++) for(int z=0;z<2;z++) sum=(sum+f[k][x][y][z])%mod; return sum; } void prepare(){ for(int i=1;i<=100;i++) s[i]='9'; for(int i=1;i<=100;i++) h[i]=calculate(i); } int main() { prepare(); T=read(); while(T--){ ans=0; scanf("%s",s+1); len=strlen(s+1); for(int i=1;i<len;i++) ans=(ans+h[i])%mod; ans=(ans+calculate(len))%mod; printf("%d\n",ans); } return 0; }