hdu_3555 bomb

数位动态规划 
    数位动态规划是求解一个大区间[L, R]中间满足条件Q的所有数字的个数(或者和,或其他)的一种方法。它通过分析每一位上的数字,一般用 dp[len][digit][...] 来表示状态“len位长的数字,最高位数字为digit所具有的xx特性”,利用记忆化搜索保存中间结果,从而加快求解速度。 
    通过求 f(n) 从0到n中满足条件Q的数字的个数,则所求的结果为 f(R) - f(L-1).

题目大意 
    给定数字n,找出从0到n中满足条件“数字k中有49(4和9连续)存在”的数字的个数。

题目分析 
    直接数位dp即可。

实现

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
typedef long long ll;
ll dp[30][10]; //dp[len][digit]表示长度为len,且最高位为digit的满足条件Q的数字个数
ll base[30];
int bits[30];
ll Dfs(int len, int digit, bool end_flag, ll n){
	if (len <= 1)
		return 0;
	if (!end_flag && dp[len][digit] != -1)
		return dp[len][digit];

	ll ans = 0;
	int end = end_flag ? bits[len - 2] : 9;
	for (int i = 0; i <= end; i++){		
		if (digit == 4 && i == 9){
			if (end_flag)
				ans += (1 + n % base[len - 2]);
			else
				ans += base[len - 2];
		}else
			ans += Dfs(len - 1, i, end_flag && (i == end), n);
	}
	if (!end_flag)
		dp[len][digit] = ans;
	return ans;
}
int Init(ll n){
	memset(bits, 0, sizeof(bits));
	int k = 0;
	base[0] = 1;
	while (n){		
		bits[k++] = n % 10;
		base[k] = base[k - 1] * 10;
		n /= 10;
	}
	return k;
}
ll Solve(ll n){
	int len = Init(n);
	return Dfs(len + 1, 0, true, n);
}
int main(){
	int T;
	ll num;
	scanf("%d", &T);
	memset(dp, -1, sizeof(dp));
	while (T--){
		scanf("%I64d", &num);
		ll ret = Solve(num);
		printf("%I64d\n", ret);
	}
	return 0;
}

在数据范围较大的时候,使用 long long int类型,但要注意所有使用long long int类型的变量被调用的函数中,参数形式均保持一致为long long int。

posted @ 2016-05-05 21:38  农民伯伯-Coding  阅读(181)  评论(0编辑  收藏  举报