HDU 2089 不要62 (数位DP)

Description

统计区间\([L,R]\)内不含“4”和“62”的数的个数。

Input

多组用例,每组用例输入\(L\)\(R\),以\(0\) \(0\)结束。\(1 \leqslant L \leqslant R \leqslant 10^6\)

Output

对于每组用例,输出一个整数,表示满足条件的数的个数。

Sample Input

1 100
0 0

Sample Output

80

Solution

数位DP。对数字的限制条件有两个,当前位不能为\(4\)和当上一位为\(6\)时当前位不能为\(2\)。定义\(dp[pos][1]\)表示从\(pos+1\)位为\(6\)时从第\(pos\)位到第\(0\)位任意取时满足条件的数的数量,\(dp[pos][0]\)表示\(pos+1\)位不为\(6\)时的情况。DFS记忆化搜索即可。

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 10;

int dp[N][2], a[N];

int dfs(int pos, bool s, bool fp)
{
	if (pos < 0) return 1;
	if (!fp && dp[pos][s] != -1) return dp[pos][s];
	int ans = 0, fpmax = fp ? a[pos] : 9;
	for (int i = 0; i <= fpmax; i++)
	{
		if (i == 4 || s && i == 2) continue;
		ans += dfs(pos - 1, i == 6, fp && i == fpmax);
	}
	if (!fp) dp[pos][s] = ans;
	return ans;
}

int calc(int n)
{
	int len = 0;
	while (n) a[len++] = n % 10, n /= 10;
	return dfs(len - 1, false, true);
}

int main()
{
	int l, r;
	memset(dp, -1, sizeof(dp));
	while (scanf("%d%d", &l, &r), l || r)
	{
		int ans = calc(r) - calc(l - 1);
		printf("%d\n", ans);
	}
	return 0;
}

http://acm.hdu.edu.cn/showproblem.php?pid=2089

posted @ 2017-08-24 10:42  达达Mr_X  阅读(134)  评论(0编辑  收藏  举报