BZOJ 1026: [SCOI2009]windy数( dp )
dp..dp(x, t) 表示共x位, 第x位为t有多少个windy数.
对答案差分, 我们只需统计1 ~ l-1和1 ~ r的windy数数量.
考虑如何计算[1, n]的答案 : 从最高位到最低位依次计算, 假设n的最高位x的数为t, 那么dp(x, 0 ~ t-1)对答案都有贡献, 然后假设最高位为x, 计算下一位..
细节很多...
---------------------------------------------------------------------------------
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 15;
const int N = 10;
int dp[MAXN][MAXN];
void init() {
memset(dp, 0, sizeof dp);
for(int i = 0; i < N; i++) dp[1][i] = 1;
for(int i = 1; i++ < N; )
for(int j = 0; j < N; j++)
for(int k = 0; k < N; k++) if(abs(k - j) >= 2)
dp[i][j] += dp[i - 1][k];
}
// [1, x]
int f(int t) {
int s[MAXN], n = 0, ans = 0;
bool F = true;
for(; t; t /= 10) s[++n] = t % 10; s[n + 1] = -2;
for(int i = n; i; i-- ) {
for(int j = 1; j < N; j++) ans += dp[i - 1][j];
if(!F) continue;
for(int j = i == n ? 1 : 0; j < s[i] || (i == 1 && j == s[i]); j++)
if(abs(s[i + 1] - j) >= 2) ans += dp[i][j];
if(abs(s[i] - s[i + 1]) < 2) F = false;
}
return ans;
}
int main() {
init();
int l, r; scanf("%d%d", &l, &r);
printf("%d\n", f(r) - f(l - 1));
return 0;
}
---------------------------------------------------------------------------------
1026: [SCOI2009]windy数
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4039 Solved: 1809
[Submit][Status][Discuss]
Description
windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,在A和B之间,包括A和B,总共有多少个windy数?
Input
包含两个整数,A B。
Output
一个整数。
Sample Input
【输入样例一】
1 10
【输入样例二】
25 50
1 10
【输入样例二】
25 50
Sample Output
【输出样例一】
9
【输出样例二】
20
9
【输出样例二】
20
HINT
【数据规模和约定】
100%的数据,满足 1 <= A <= B <= 2000000000 。