HDU6148 Valley Numer(数位DP)

HDU6148 Valley Numer(数位DP)

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

题意

查找区间[0,n]内有多少个数字上没有峰值的数字。注意12221也算有峰值。

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
#include<functional> 
#include<map>
#include<unordered_map>
#define lowbit(x) ((x)&-(x));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e5+10,NN=1e3+10,INF=0x3f3f3f3f,LEN=110;
const ll MOD=1e9+7;
const ull seed=31;
ll digit[LEN];
ll dp[LEN][10][3];//三维下标为0表示不确定前面的状态,1表示递减,2表示递增
ll dfs(ll len,bool ismax,ll isup,ll last,bool lead_zero){//lead_zero表示是否处理到了可以处理的数字,意思就是是否已经抛弃了前导零
	ll ans=0;
	if(!len) return lead_zero?1LL:0LL;//若已经抛弃前导零找到可以处理的数字则输出1
	if(!ismax&&dp[len][last][isup]!=-1) return dp[len][last][isup];
	ll maxx=ismax?digit[len]:9LL;
	for(ll i=0;i<=maxx;i++){
		if(isup==2&&i<last) continue;//若isup已经为2就是之前已经出现递增,若i<last则在递增后又出现了递减,不允许出现这种情况,跳过
		else if(!lead_zero&&i==0) ans=(ans+dfs(len-1,ismax&&i==maxx,isup,i,false))%MOD;//若还在前导零的范围内并且i还是0,则lead_zero继续为false
		else if(!lead_zero) ans=(ans+dfs(len-1,ismax&&i==maxx,isup,i,true))%MOD;//若找到了可以处理的数字并且这个数字之前是前导零
		else if(i==last) ans=(ans+dfs(len-1,ismax&&i==maxx,isup,i,true))%MOD;//若i与前一个相同
		else ans=(ans+dfs(len-1,ismax&&i==maxx,i>last?2:1,i,true))%MOD;//若不同
	}
	if(!ismax) dp[len][last][isup]=ans;
	return ans;
}
ll solve(char str[]){
	ll len=0;
	for(ll i=strlen(str)-1;i>=0;i--) digit[++len]=str[i]-'0';
	return dfs(len,true,0,-1,false);
} 
void init(){
	memset(dp,-1,sizeof dp);
}
int main(){
	int t;
	scanf("%d",&t);
	init();
	while(t--){
		char n[NN];
		scanf("%s",n);
		printf("%lld\n",solve(n));
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Hc_Soap/article/details/107665191