2017广东工业大学程序设计竞赛决赛:G. 等凹数字(数位DP)


Problem G: 等凹数字

Description

定义一种数字称为等凹数字,即从高位到地位,每一位的数字先非递增再非递减,不能全部数字一样,且该数是一个回文数,即从左读到右与从右读到左是一样的,仅形成一个等凹峰,如5432123455544334455是合法的等凹数字,543212346123321,111111不是等凹数字。现在问你[L,R]中有多少等凹数字呢?

Input

第一行一个整数T,表示数据的组数。

接下来T行每行俩个数字L和R,(1<=L<=R<=1e18)

Output

 输出一个整数,代表[L,R]中有多少等凹数字

Sample Input

2
1 100
101 200

Sample Output

0
1

HINT

 小于等于2位的数字无凹峰


感觉很多数位dp都可以直接用这道题的程序改

因为这道题又有递增又要递减,还加个回文

复杂但难度也不是特别高

dp[len][pos][pre][up][down][hw]

分别表示:当前有效长度(去掉前导0后);枚举到了第pos位;上一个数字是pre

是否递增过;是否递减过;是否回文

#include
#include
#define LL long long
long long str[20], temp[20], dp[20][20][10][3][3][3];
long long Sech(LL len, LL pos, LL pre, LL up, LL down, LL hw, LL flag, LL k)
{
	LL u, i, ans;
	if(pos<0)
	{
		if(up && down && hw)
			return 1;
		return 0;
	}
	if(flag==0 && k==0 && dp[len][pos][pre][up][down][hw]!=-1)
		return dp[len][pos][pre][up][down][hw];
	if(flag==1)  u = str[pos];
	else  u = 9;
	ans = 0;
	for(i=0;i<=u;i++)
	{
		temp[pos] = i;
		if(k==1)
		{
			ans += Sech(len-(k && i==0), pos-1, i, 0, 0, hw, flag && i==u, k && (i==0));
			continue;
		}
		if(i==pre)
		{
			if(hw && pos<(len+1)/2)
				ans += Sech(len, pos-1, i, up, down, i==temp[len-pos], flag && i==u, k && (i==0)); 
			else
				ans += Sech(len, pos-1, i, up, down, hw, flag && i==u, k && (i==0));
		}
		else if(i>pre)
		{
			if(down==0)
				continue;
			if(hw && pos<(len+1)/2)
				ans += Sech(len, pos-1, i, 1, down, i==temp[len-pos], flag && i==u, k && (i==0));
			else
				ans += Sech(len, pos-1, i, 1, down, hw, flag && i==u, k && (i==0));
		}
		else if(i

你可能感兴趣的:(动态规划)