【HDU3555】Bomb

题目链接

Bomb

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 26679    Accepted Submission(s): 10102


Problem Description
The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the time bomb. The number sequence of the time bomb counts from 1 to N. If the current number sequence includes the sub-sequence "49", the power of the blast would add one point.
Now the counter-terrorist knows the number N. They want to know the final points of the power. Can you help them?
 

Input
The first line of input consists of an integer T (1 <= T <= 10000), indicating the number of test cases. For each test case, there will be an integer N (1 <= N <= 2^63-1) as the description.

The input terminates by end of file marker.
 

Output
For each test case, output an integer indicating the final points of the power.
 

Sample Input
3 1 50 500
 

Sample Output
0 1 15
Hint
From 1 to 500, the numbers that include the sub-sequence "49" are "49","149","249","349","449","490","491","492","493","494","495","496","497","498","499", so the answer is 15.
 

Author
fatboy_cw@WHU
 

Source
 

Recommend
zhouzeyong
 

Statistic | Submit | Discuss | Note

题解

此题题意就是给你T个n,找出n以内的包含49的数的个数。
很裸的一题数位dp。
直接dp包含49的数的个数有点麻烦,所以我先算出不包含49的数的个数,然后用n+1来减(因为计算不包含49的数中是包括0的,所以减了之后还要加1)。
在搜索的过程中记录三个数,l表示当前是第几位,mach表示上一位是否为4,upp表示之前的位数是否都是取最大值,如果之前的数都是取最大值,当前的位只能取0到n的当前位,而不是0到9.
然后开始搜索,出现连续的49就跳过。
dp[j][i]记录第j位时上一位是否为4(i表示)不包含49的数的个数,用记忆化,如果搜过就直接加上。
因为上一位是否为4决定了当前位能否为9,对后面数的个数有影响,所以要加一维i。
上代码

#include<bits/stdc++.h>
using namespace std;
int t;
long long n;
int l,a[109];
long long dp[109][3];
long long dfs(int l,bool mach,bool upp) {
	if(l<=0) return 1;
	if(upp==0 && dp[l][mach]!=-1) return dp[l][mach];
	int up;
	if(upp==1) up=a[l];
	else up=9;
	long long sum=0;
	for(int j=0; j<=up; j++) {
		if(mach==1 && j==9) continue;
		sum+=dfs(l-1,j==4,upp==1 && j==up);
	}
	if(upp==0) dp[l][mach]=sum;
	return sum;
}
long long ans(long long x) {
	while(x>0) {
		l++;
		a[l]=x%10;
		x/=10;
	}
	return dfs(l,0,1);
}
int main() {
	scanf("%d",&t);
	memset(dp,-1,sizeof(dp));
	while(t--) {
		scanf("%lld",&n);
		l=0;
		printf("%lld
",n+1-ans(n));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/linjiale/p/9872742.html