[SCOI2009] windy数

类型:数位DP

传送门:>Here<

题意:不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。求区间$[A, B]$内的windy数个数

解题思路

不看题解一遍A这题也是很水的,怪不得洛谷的难度只有蓝

其实这道题就是需要处理前导零的数位DP。状态还是一样:$dp[i][j]$表示$i$位数开头为$j$的方案数,累积的时候判断abs是否小于2即可

至于前导零的处理,还是和前面一题一样,先做$0 \rightarrow len-1$位的(枚举1),然后做$len$位的即可

总结一下需要处理前导零的数位DP:

由于前导零在且只在第一位时会对答案造成影响,因此只需要特殊处理第一位即可。

在枚举$0 \rightarrow len-1$中的数时,枚举的始终都是第一位,并且是毫无上限限制的,因此只需要从1~9枚举并且直接累积$dp[i][j]$。

对于$len$位处理时,不能碰到上限,并且特判第len位不能取0,其他可以取。

Code

/*By DennyQi 2018.8.13*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define  r  read()
#define  Max(a,b)  (((a)>(b)) ? (a) : (b))
#define  Min(a,b)  (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int MAXN = 10010;
const int MAXM = 27010;
const int INF = 1061109567;
inline int read(){
    int x = 0; int w = 1; register int c = getchar();
    while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
    if(c == '-') w = -1, c = getchar();
    while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar(); return x * w;
}
int N,M;
int dp[12][12],digit[12];
inline int ABS(int x){
    return x<0 ? -x : x;
}
inline void Init(){
    for(int j = 0; j <= 9; ++j){
        dp[1][j] = 1;
    }
    for(int i = 2; i <= 11; ++i){
        for(int j = 0; j <= 9; ++j){
            for(int k = 0; k <= 9; ++k){
                if(ABS(j-k) < 2) continue;
                dp[i][j] += dp[i-1][k];
            }
        }
    }
}
inline int cul(int x){
    int y = x;
    int len = 0, res = 0;
    while(y > 0){
        digit[++len] = y % 10;
        y /= 10;
    }
    digit[len+1] = -100;
    for(int i = len-1; i; --i){
        for(int j = 1; j <= 9; ++j){
            res += dp[i][j];
        }
    }
    for(int i = len; i; --i){
        for(int j = 0; j < digit[i]; ++j){
            if(i == len && j == 0) continue;
            if(ABS(digit[i+1]-j) < 2) continue;
            res += dp[i][j];
        }
        if(ABS(digit[i+1]-digit[i]) < 2) break;
    }
    return res;
}
int main(){
    N = r, M = r;
    Init();
    printf("%d", cul(M+1)-cul(N));
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/qixingzhi/p/9468955.html