1. 程式人生 > >#108-【數位DP】Bomb

#108-【數位DP】Bomb

Description

反恐怖主義分子在塵土中發現了一枚計時炸彈。 但是這次恐怖分子改進了定時炸彈。 計時炸彈的數字序列從1到N.如果當前數字序列包含子序列“49”,爆炸的力量將增加一點。

現在反恐怖主義分子知道數字N, 他們想要知道威力的最終點。 你能幫助他們嗎?

 

Input

第一行輸入由整數T(1 <= T <= 10000)組成,表示測試用例數。 對於每個測試用例,將會有一個整數N(1 <= N <= 2 ^ 63-1)作為描述。輸入以檔案標記的末尾終止。

 

Output

對於每個測試用例,輸出指示功率的最終點的整數。



 

Sample Input

3
1
50
500

Sample Output

0
1
15

很模板

// 和不要62是同一個難度等級

#include <iostream>
#include <cstring>

#define SIZE 110

using namespace std;

long long dp[SIZE][2];
short a[SIZE];

long long dfs(int pos, bool is4, bool havelimit) // 數位DP
{
	long long res = 0;
	int i, len;
	
	if (!pos)
	{
		return 1;
	}
	if ((!havelimit) && (~dp[pos][is4]))
	{
		return dp[pos][is4];
	}
	len = (havelimit) ? a[pos] : 9;
	for (i = 0; i <= len; ++i)
	{
		if ((is4) && (i == 9)) // 包含了49
		{
			continue;
		}
		res += dfs(pos - 1, i == 4, ((havelimit) && (i == len)));
	}
	if (!havelimit)
	{
		dp[pos][is4] = res;
	}
	
	return res;
}

long long doit(int n)
{
	long long pos = 0;
	
	while (n)
	{
		a[++pos] = n % 10;
		n /= 10;
	}
	
	return dfs(pos, false, true);
}

int main(int argc, char** argv)
{
	long long a;
	int t;
	
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d", &a);
		memset(dp, -1, sizeof (dp));
		printf("%lld\n", a + 1 - doit(a)); // 那麼運算結果就是包含49的數字的個數
	}
	
	return 0;
}