[BZOJ 1026] [SCOI 2009] Windy数 【数位DP】

题目链接:BZOJ - 1026

题目分析

这道题是一道数位DP的基础题,对于完全不会数位DP的我来说也是难题..

对于询问 [a,b] 的区间的答案,我们对询问进行差分,求 [0,b] - [0,a-1] 的答案。这样就化繁为简了。

具体过程见代码中的注释。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;

const int MaxBit = 13;

int A, B;
int f[MaxBit][11], Bit[MaxBit];

inline int Abs(int a) {
	return a >= 0 ? a : -a;
}

//计算小于x的数的答案
int Get(int x) {
	if (x == 0) return 0;
	int ret = 0, l = 0;
	while (x) {
		Bit[++l] = x % 10;
		x /= 10;
	}
	//统计位数不足l位的答案
	for (int i = 1; i <= l - 1; ++i) {
		for (int j = 1; j <= 9; ++j) {
			ret += f[i][j];
		}
	}
	//固定后面的(l-i)位,然后第i位可以在[0, Bit[i]-1]之间变化
	for (int i = 1; i <= Bit[l] - 1; ++i) ret += f[l][i];
	for (int i = l - 1; i >= 1; --i) {
		for (int j = 0; j <= Bit[i] - 1; ++j) {
			if (Abs(j - Bit[i + 1]) >= 2) ret += f[i][j];
		}
		//无法固定第i位
		if (Abs(Bit[i + 1] - Bit[i]) < 2) break;
	}
	return ret;
}

int main()
{
	//f[i][j]表示第i位是j的答案数
	for (int i = 0; i <= 9; ++i) f[1][i] = 1;
	for (int i = 1; i <= 10; ++i) {
		for (int j = 0; j <= 9; ++j) {
			for (int k = 0; k <= 9; ++k) {
				if (Abs(k - j) >= 2) f[i][j] += f[i - 1][k];
			}
		}
	}
	scanf("%d%d", &A, &B);
	//对询问进行差分,化繁为简
	printf("%d\n", Get(B + 1) - Get(A));
	return 0;
}

  

时间: 2024-10-17 21:09:15

[BZOJ 1026] [SCOI 2009] Windy数 【数位DP】的相关文章

[BZOJ 1026][SCOI 2009]windy数(数位DP)

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1026 很基础的数位DP题,很早之前我就尝试做这题,不过当时我被这题吓死了,现在回过头做这题,感觉简单多了. 做这个题时我想到了POJ一道类似的组合数学的题,同样是按数位统计,有异曲同工之妙. 题目要求[a,b]区间上的windy数个数,我们可以转化成求[1,a]上的windy数个数-[1,b-1]上的windy数个数.题目转化成了求[1,x]上的windy数个数,我们就写个函数c

USETC 250 windy数 数位DP

注意处理数字只有一位的情况(其实不用怎么处理)= = 简单数位DP #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #

bzoj 1026 windy数(数位DP)

1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 2615  Solved: 1155 [Submit][Status] Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? Input 包含两个整数,A B. Output 一个整数. Sample Input [

bzoj 1026 [SCOI2009]windy数 数位dp

1026: [SCOI2009]windy数 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1026 Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? Input 包含两个整数,A B. Output 一个整数.

bzoj 1026 [ SCOI2009 ] windy数 —— 数位DP

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1026 蛮简单的数位DP,预处理 f[i][j] 表示 i 位数,以 j 开头的 windy 数个数: 但不明白为什么最后一位拿出来特判 ret++  不对,而写在循环里,特判 i==1 就对了... 代码如下: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm&g

bzoj 1026 [SCOI2009]windy数——数位dp水题

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1026 迷恋上用dfs写数位dp了. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=15; int l,r,dg[N],dp[N][N]; int dfs(int p,int lst,bo

HYSBZ 1026 windy数 数位dp

点击打开链接 windy数 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 3038  Solved: 1361 [Submit][Status] Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? Input 包含两个整数,A B. Output 一个整数. Sample Input [输入样例一] 1

1026: [SCOI2009]windy数 (数位DP)

Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? Input 包含两个整数,A B. Output 一个整数 Sample Input [输入样例一] 1 10 [输入样例二] 25 50 Sample Output [输出样例一] 9 [输出样例二] 20 HINT [数据规模和约定] 100%的数据,满足 1 <= A <= B <= 20

bzoj1026: [SCOI2009]windy数 数位dp

题目: http://www.lydsy.com/JudgeOnline/problem.php?id=1026 题意: Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之间,包括A和B,总共有多少个windy数? Input 包含两个整数,A B. Output 一个整数 思路: 数位dp,记忆化搜索. 1 #include <bits/stdc++.h> 2 3 using namesp