百度之星复赛T5 Valley Numer

Posted CQzhangyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了百度之星复赛T5 Valley Numer相关的知识,希望对你有一定的参考价值。

Valley Numer

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。用f[i][j][0/1/2]表示i位,最高位为j,当前处于 递减/递增/平 状态的数的个数。然后尽情讨论吧!

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
ll f[110][12][3];
//0 减 1 增 2 未知
int v[110];
char str[110];
ll ans;
int n,tag,tmp;
void init()
{
	int i,j,k;
	for(i=0;i<=9;i++)	f[1][i][2]=1;
	for(i=2;i<=100;i++)
	{
		for(j=0;j<=9;j++)
		{
			f[i][j][2]=f[i-1][j][2];
			for(k=0;k<=9;k++)
			{
				if(j<=k)	f[i][j][1]=(f[i][j][1]+f[i-1][k][1])%mod;
				if(j<k)	f[i][j][1]=(f[i][j][1]+f[i-1][k][2])%mod;
				if(j>=k)	f[i][j][0]=(f[i][j][0]+f[i-1][k][0])%mod;
				if(j>k)	f[i][j][0]=(f[i][j][0]+f[i-1][k][1]+f[i-1][k][2])%mod;
			}
		}
	}
}
void work()
{
	scanf("%s",str),n=strlen(str);
	int i,j;
	ans=0,tag=2;
	for(i=1;i<=n;i++)	v[i]=str[n-i]-‘0‘;
	for(i=1;i<n;i++)	for(j=1;j<=9;j++)	ans=(ans+f[i][j][0]+f[i][j][1]+f[i][j][2])%mod;
	for(i=n;i>=1;i--)
	{
		for(j=(i==n)?1:0;j<v[i];j++)
		{
			tmp=tag;
			if(i!=n&&j>v[i+1])	tmp=1;
			if(i!=n&&j<v[i+1])
			{
				if(tag==1)	continue;
				tmp=0;
			}
			if(tmp==2)
			{
				ans=(ans+f[i][j][0]+f[i][j][1]+f[i][j][2])%mod;
			}
			if(tmp==1)
			{
				if(j>=v[i+1])	ans=(ans+f[i][j][1]+f[i][j][2])%mod;
			}
			if(tmp==0)
			{
				if(j<=v[i+1])	ans=(ans+f[i][j][0]+f[i][j][1]+f[i][j][2])%mod;
				if(j>v[i+1])	ans=(ans+f[i][j][1]+f[i][j][2])%mod;
			}
		}
		if(i!=n&&v[i]>v[i+1])	tag=1;
		if(i!=n&&v[i]<v[i+1])
		{
			if(tag==1)	break;
			tag=0;
		}
	}
	if(!i)	ans=(ans+1)%mod;
	printf("%lld\n",ans);
}
int main()
{
	int T;
	init();
	scanf("%d",&T);
	while(T--)	work();
	return 0;
}//1 130

以上是关于百度之星复赛T5 Valley Numer的主要内容,如果未能解决你的问题,请参考以下文章

2017"百度之星"程序设计大赛 - 复赛1005&&HDU 6148 Valley Numer数位dp

HDU6148 Valley Numer

百度之星2018 复赛 体验记

HDU 6148 Valley Numer(数位DP)

2016百度之星复赛 1003 拍照 优先队列

比赛百度之星2017 复赛