Valley Numer HDU - 6148
原题链接
考察:数位dp
思路:
定义一个变量st,目前枚举的数字的状态.
- st==0 跟上位比递减
- st==1 跟上位比严格递增
- st==2 出现了山峰现象.
- 如果出现了与上位相等或者之前出现了山峰现象,直接把状态传递下去.
Code
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const int M = 1000000007,N = 110,S=10;
char s[N];
int a[N];
LL f[N][N][N];
LL dfs(int ns,int pos,int last,int st,bool limit,bool lead)
{
if(!pos) return st!=2;
if(!limit&&!lead&&f[pos][last][st]!=-1) return f[pos][last][st];
int up = limit?a[pos]:9;
LL res = 0;
for(int i=0;i<=up;i++)
{
if(lead&&!i) res+=dfs(ns*10+i,pos-1,last,st,limit&&i==up,lead&&!i);
else if(st==2||i==last) res+=dfs(ns*10+i,pos-1,i,st,limit&&i==up,lead&&!i);
else if(i>last) res+=dfs(ns*10+i,pos-1,i,1,limit&&i==up,lead&&!i);
else if(i<last&&st==1) res+=dfs(ns*10+i,pos-1,i,2,limit&&i==up,lead&&!i);
else res+=dfs(ns*10+i,pos-1,i,0,limit&&i==up,lead&&!i);
res%=M;
}
if(!lead&&!limit) f[pos][last][st] = res%M;
return res;
}
LL solve()
{
scanf("%s",s+1);
int len = strlen(s+1);
for(int i=len;i>0;i--) a[len-i+1] = s[i]-'0';
return dfs(0,len,11,0,1,1);
}
int main()
{
int T;
scanf("%d",&T);
memset(f,-1,sizeof f);
while(T--) printf("%lld\n",solve()-1);
return 0;
}