一本通1589:不要 62

一本通1589:不要 62

原题链接
写在前面:在校内oj一次模拟赛中有这道题,在洛谷上找了找,结果没有,没想到在一本通上找到了

数位dp

数位dp裸题

不多说了,直接上代码吧(有注释)

不会真的有人写数位dp不用深搜吧QWQ

#include <bits/stdc++.h>

using namespace std;

int l, r, len;
int num[15], dp[15][15][2];		//dp[len][pre][lim] 解释见下

int dfs(int len, int pre, int lim){		//len:倒着处理到第len位(实际上对于x是正着处理每一位)。pre:上一位是几(判断62)。lim:是否有上界
	if(!len) return 1;	//处理完了,返回1
	if(dp[len][pre][lim] != -1) return dp[len][pre][lim];	//记忆化
	int res = lim ? num[len] : 9;		//找出上界
	int ans = 0;
	for(int i = 0; i <= res; i++){
		if(i == 4 || (pre == 6 && i == 2)) continue;	//根据题意判断
		ans += dfs(len - 1, i, lim && (i == res));		//正常搜索
	}
	return dp[len][pre][lim] = ans;
}

int solve(int x){
	len = 0;
	while(x){
		num[++len] = x % 10;		//注意这里是倒着存x的每一位,看到这里后可以再去理解一下上面的len
		x /= 10;
	}
	memset(dp, -1, sizeof(dp));		//注意dp数组初值-1,因为有许多情况dp值为0,无法判断是否计算过
	return dfs(len, 0, 1);			//刚开始第一位就有上界,所以lim初值为1
}

int main(){
	while(scanf("%d%d", &l, &r) && l && r)
		printf("%d
", solve(r) - solve(l - 1));	//利用前缀和思想,计算答案
	return 0;
}

本文来自博客园,作者:xixike,转载请注明原文链接:https://www.cnblogs.com/xixike/p/15103489.html

原文地址:https://www.cnblogs.com/xixike/p/15103489.html