Valley Numer HDU - 6148

原题链接
考察:数位dp
思路:
  定义一个变量st,目前枚举的数字的状态.

  1. st==0 跟上位比递减
  2. st==1 跟上位比严格递增
  3. st==2 出现了山峰现象.
  4. 如果出现了与上位相等或者之前出现了山峰现象,直接把状态传递下去.

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;
}
posted @ 2021-05-31 12:00  acmloser  阅读(39)  评论(0编辑  收藏  举报