链接:BZOJ1026

题意:【A,B】区间内,有多少个所有相邻数位数值之差不小于2的数


还是来想记忆化的数位DP

首先len肯定是一维变量,flag是一维,既然相邻数位数值有关系,那么上一位数值必须要记录,设为before

如果就dp【len】【before】行吗?


可以,但是dfs记忆化的时候,就三维变量是不行的

因为要判断最高位和前导0

当最高位枚举的时候,可以是0,从前到后一直是0也可以,但是这个数是0,并且只能算作一次

所以呢,记忆化的时候,需要一个bool变量,zero


zero为1,说明之前枚举的高位已经有值了

zero为0,说明之前枚举的高位一直是0,如果一直是0,也不能在记忆化的时候直接返回,跟flag的道理是一样的


其他细节见代码

long long m,n,dp[20][10];
int digit[20];

long long dfs(int pos,int before,bool zero,bool flag){
	if (pos==0) return 1;
	if (flag&&dp[pos][before]!=-1&&zero) return dp[pos][before];
	long long ans=0;
	int num=flag?9:digit[pos];
	for(int i=0;i<=num;i++)
		if (!zero||abs(before-i)>=2)
			ans+=dfs(pos-1,i,zero||i>0,flag||i<num);
	if (flag&&zero) dp[pos][before]=ans;
	return ans;
}

long long calc(long long x){
	int len=0;
	while(x){
		digit[++len]=x%10;
		x/=10;
	}
	return dfs(len,11,0,0);
}

int main(){
	//input;
	memset(dp,-1,sizeof(dp));
	while(scanf("%lld%lld",&m,&n)!=EOF)
		printf("%lld\n",calc(n)-calc(m-1));
	return 0;
}