洛谷P2657 Loj10165 SCOI2009 windy数

题目描述

windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,

在A和B之间,包括A和B,总共有多少个windy数?

输入输出格式

输入格式:

 

包含两个整数,A B。

 

输出格式:

 

一个整数

 

数位DP,记录每一位最后一位是什么,枚举时如果他们的差小于2就return。

但是注意!如果有前导零,也就是00014是一个合法的序列,但是一般会判断1和0差小于2,就算非法了。

我们需要记录前导零,如果当前是前导零,则默认当前位位-10000,也就是下一位随便取。

 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#define in(a) a=read()
#define REP(i,k,n)  for(int i=k;i<=n;i++)
using namespace std;
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar())
        if(ch=='-')
            f=-1;
    for(;isdigit(ch);ch=getchar())
        x=x*10+ch-'0';
    return x*f;
}
int a,b,digit[20],dp[20][20],ind;
inline int dfs(int pos,int state,bool ze,bool flag){
    if(!pos)  return 1;
    if(!ze && dp[pos][state] && !flag)  return dp[pos][state];
    int up,ans=0;
    if(flag)  up=digit[pos];
    else  up=9;
    REP(i,0,up){
        if(abs(i-state)<2)  continue;
        if(ze && !i)  ans+=dfs(pos-1,-1000000,1,flag && i==digit[pos]);
        else  ans+=dfs(pos-1,i,0,flag && i==digit[pos]);
    }
    if(!flag && !ze)  dp[pos][state]=ans;
    return ans;
}
inline int solve(int x){
    ind=0;
    while(x){
        digit[++ind]=x%10;
        x/=10;
    }
    memset(dp,0,sizeof(dp));
    return dfs(ind,-1000000,1,1);
}
int main(){
    in(a),in(b);
    printf("%d",solve(b)-solve(a-1));
}
    

 

posted @ 2018-10-25 20:30  Dijkstra·Liu  阅读(292)  评论(0编辑  收藏  举报