洛谷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)); }