[luoguP2657] [SCOI2009]windy数(数位DP)

Posted 蒟蒻zht的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[luoguP2657] [SCOI2009]windy数(数位DP)相关的知识,希望对你有一定的参考价值。

传送门

 

f[i][j]表示位数为i,第i位为j的windy数的个数

先预处理出f数组。

求的时候先算没有前导0的答案,再算位数和给定的数相同的答案。

 

#include <cmath>
#include <cstdio>
#include <cstring>

using namespace std;

int f[15][10], d[15];

inline void init()
{
	int i, j, k;
	for(i = 0; i <= 9; i++) f[1][i] = 1;
	for(i = 2; i <= 10; i++)
		for(j = 0; j <= 9; j++)
			for(k = 0; k <= 9; k++)
				if(abs(j - k) >= 2) f[i][j] += f[i - 1][k];
}

inline int query(int x)
{
	int i, j, ret = 0;
	memset(d, 0, sizeof(d));
	for(; x; x /= 10) d[++d[0]] = x % 10;
	for(i = 1; i < d[0]; i++)
		for(j = 1; j <= 9; j++) ret += f[i][j];
	for(i = d[0]; i >= 1; i--)
	{
		for(j = 0; j < d[i]; j++)
		{
			if(i == d[0] && !j) continue;
			if(i == d[0]) ret += f[i][j];
			else if(abs(d[i + 1] - j) >= 2) ret += f[i][j];
		}
		if(i != d[0] && abs(d[i + 1] - d[i]) < 2) break;
	}
	return ret;
}

int main()
{
	int l, r;
	init();
	scanf("%d %d", &l, &r);
	printf("%d\n", query(r + 1) - query(l));
	return 0;
}

  

 

以上是关于[luoguP2657] [SCOI2009]windy数(数位DP)的主要内容,如果未能解决你的问题,请参考以下文章

luogu P2657 [SCOI2009]windy数 数位dp 记忆化搜索

P2657 [SCOI2009]windy数

P2657 [SCOI2009]windy数

P2657 [SCOI2009] windy 数

P2657 [SCOI2009]windy数

P2657 [SCOI2009]windy数 (数位DP)