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 MB
Submit: 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

Sample Output

【输出样例一】
9
【输出样例二】
20

HINT

【数据规模和约定】

100%的数据,满足 1 <= A <= B <= 2000000000 。

Source

posted @ 2015-09-03 16:54  JSZX11556  阅读(...)  评论(... 编辑 收藏