BZOJ 1026: [SCOI2009]windy数

Posted ZlycerQan

tags:

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

二次联通门 : BZOJ 1026: [SCOI2009]windy数

 

 

 

/*
    BZOJ 1026: [SCOI2009]windy数

    水题开心
    数位dp
    f[i][j]表示一个i位的数字的第i位是j的数字有几个

    设 s (x)为[0,x)的答案
    怎么求s(x)?
    设x有t位,我们先找到所有t - 1的符合题意的数
    然后从高到低一位一位得确定为原数字x对应位上的数字
    在此基础上累计方案数就好了
    就能求出[0,x)的答案了
    然后s (M + 1) - s (N)即可
*/
#include <cstdio>

#define rg register
#define Max 20
int f[Max][Max], d[Max];
inline int abs (int x) { return x < 0 ? -x : x; }
int Calc (int x)
{
    int c = 0, res = 0; rg int i, j, k;
    for (; x; d[++ c] = x % 10, x /= 10);
    for (i = 1; i < c; ++ i)
        for (j = 1; j <= 9; ++ j) res += f[i][j];
    for (i = c; i; -- i)
    {
        for (j = (i == c); j < d[i]; ++ j)
            if (i == c || abs (j - d[i + 1]) >= 2)
                res += f[i][j];
        if (i < c && abs (d[i + 1] - d[i]) < 2) break;
    }
    return res;
}
int main (int argc, char *argv[])
{
    rg int i, j, k;
    for (i = 0; i <= 9; ++ i) f[1][i] = 1;
    for (i = 1; i <= 10; ++ i)
        for (j = 0; j <= 9; ++ j)
        {
            for (k = 0; k <= j - 2; ++ k) f[i + 1][k] += f[i][j];
            for (k = j + 2; k <= 9; ++ k) f[i + 1][k] += f[i][j];
        }
    int N, M;
    scanf ("%d%d", &N, &M);
    printf ("%d", Calc (M + 1) - Calc (N));

    return 0;
}

 

以上是关于BZOJ 1026: [SCOI2009]windy数的主要内容,如果未能解决你的问题,请参考以下文章

数位DP BZOJ 1026 [SCOI2009]windy数

BZOJ 1026: [SCOI2009]windy数

bzoj1026 [SCOI2009]windy数

[bzoj1026][SCOI2009]windy数

BZOJ1026: [SCOI2009]windy数

bzoj1026 SCOI2009—windy数