2019暑假集训 windy数

题目描述
Windy 定义了一种 Windy 数:不含前导零且相邻两个数字之差至少为2的正整数被称为 Windy 数。

Windy 想知道,在A和B之间,包括A和B,总共有多少个 Windy 数?
输入
一行两个数,分别为A,B。
输出
输出一个整数,表示答案。
样例输入
样例输入 1
1 10

样例输入 2
25 50
样例输出
样例输出 1
9

样例输出 2
20
提示
20%的数据,满足1<=A<=B<=1e6;
100%的数据,满足1<=A<=B<=2e9。

又是一道裸的数位dp,但是应当注意,为了区分前导0和中间0的区别,我们将前导0看作11,
这样可以防止前导0后面不能放置1(因为差小于2),这样即可判断每一个0前面是否为前导0,若是,则该位为前导0
上代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define olinr return
#define _ 0
#define love_nmr 0;
using namespace std;
int digit[105],dp[105][105],idx,a,b;
int DP(int pos,int statu,int limit)
{
    if(!pos)return 1;
    if(!limit&&~dp[pos][statu])return dp[pos][statu];
    int res=0;
    int end=limit?digit[pos]:9;
    for(int i=0;i<=end;i++)
    {
        if(abs(statu-i)<2)continue;//差为2
        if(statu==11&&i==0)res+=DP(pos-1,11,limit&&i==end);//前导0
        else res+=DP(pos-1,i,limit&&i==end);
    }
    if(!limit)dp[pos][statu]=res;
    return res;
}
int solve(int num)
{
    memset(dp,-1,sizeof dp);
    memset(digit,0,sizeof digit);
    idx=0;
    int temp=num;
    while(temp>0)
    {
        digit[++idx]=temp%10;
        temp/=10;
    }
    return DP(idx,11,1);
}
int main()
{
    scanf("%d%d",&a,&b);
    printf("%d",solve(b)-solve(a-1));
    olinr ~~(0^_^0)*love_nmr
}

 

posted @ 2019-08-14 10:48  lqxssf  阅读(155)  评论(0编辑  收藏  举报