[SCOI2009]windy数
BZOJ
luogu
数位dp入门题
复杂度:(O(11×10×10))
详细见注释
#define ll long long
#include<bits/stdc++.h>
using namespace std;
int len,w[11];
ll a,b,f[11][10];
//前导0的bool标记就省掉了,x==-2就表示上一位是前导0
ll dfs(int p,int x,bool lim){//p第几位,x上一位是多少,lim这一位是否受最高位限制
if(!p)return 1;//搜到一个合法数
if(!lim&&x!=-2&&f[p][x]!=-1)return f[p][x];//记忆化
int up=lim?w[p]:9;ll res=0;
for(int i=0;i<=up;i++){
if(abs(i-x)<2)continue;
if(!i&&x==-2)res+=dfs(p-1,-2,lim&&(i==up));//这一位还是前导0
else res+=dfs(p-1,i,lim&&(i==up));
}
return (!lim&&x!=-2)?f[p][x]=res:res;//记忆化
}
ll solve(ll x){
len=0;
while(x){w[++len]=x%10;x/=10;}
return dfs(len,-2,1);
}
int main(){
cin>>a>>b;
memset(f,-1,sizeof(f));
printf("%lld
",solve(b)-solve(a-1));//前缀相减
return 0;
}