[SCOI2009]windy数

[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\n",solve(b)-solve(a-1));//前缀相减
	return 0;
}
posted @ 2018-10-28 22:50  sdzwyq  阅读(118)  评论(0编辑  收藏  举报