「题解」:windy数

问题: windy数

时间限制: 1 Sec  内存限制: 512 MB

题面


题目描述

Windy 定义了一种 Windy 数:不含前导零且相邻两个数字之差至少为

的正整数被称为 Windy 数。

Windy 想知道,在A和B之间,包括A和B,总共有多少个 Windy 数?

输入格式

一行两个数,分别为 A,B

输出格式

输出一个整数,表示答案。

样例输入

1 10

样例输出

9

题解


我的数位dp入门题,嗯,其实挺easy的。

设f[i][j]表示填了i位数,最高位是j的windy数的个数。

于是不考虑神特么的先导0问题单考虑一下临位差距至少为2的问题直接大力dp算出所有的值。

然后再来一遍大力dp,j从1-9循环累加答案就可以了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define int long long
#define rint register int
#define ll long long
using namespace std;
int f[20][15]={0},a,b;
ll pw[15];
void prework()
{
    pw[0]=1;
    for(rint i=1;i<=12;++i)pw[i]=pw[i-1]*10;
    for(rint i=0;i<=9;++i)f[1][i]=1;
    for(rint i=2;i<=11;++i)//枚举数位
        for(rint j=0;j<=9;++j)//枚举最高位
            for(rint k=0;k<=9;++k)//枚举上一个状态的最高位,本状态的次高位
                if(abs(j-k)>=2)f[i][j]+=f[i-1][k];
}
int count(int x)
{
    int w=0,y,ans=0,pre;
    while(pw[w]<=x)++w;//求位数
    for(rint i=1;i<w;++i)//枚举位数
        for(rint j=1;j<=9;++j)//枚举最高位
            ans+=f[i][j];
    y=x/pw[w-1];
    for(rint i=1;i<y;++i)ans+=f[w][i];
    pre=y;
    x%=pw[w-1];
    for(rint i=w-1;i>=1;--i)
    {
        y=x/pw[i-1];
        for(rint j=0;j<y;++j)
            if(abs(j-pre)>=2)
                ans+=f[i][j];
        if(abs(pre-y)<2)break;
        pre=y;
        x%=pw[i-1];
    }
    return ans;
}
signed main()
{
    scanf("%lld %lld",&a,&b);
    prework();
    cout<<count(b+1)-count(a)<<endl;
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/xingmi-weiyouni/p/11311352.html