hdoj Bomb 3555 (数位DP)好题

Bomb

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


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
2010 ACM-ICPC Multi-University Training Contest(12)——Host by WHU
//题意:
给你一个数N,问你从1---N之间有几个数含有49.
//思路:
先打表,将可能出现的情况数存起来:
dp[i][0]表示前i位有49的情况数;
dp[i][1]表示前i位没有49并且第一位的数为9的情况数;
dp[i][2]表示前i位没有49并且第一位不是9的情况数;
然后从高位向下模拟累加,已经枚举过的位默认为该位最大值。当前位最大值为x,我们就算填0..x-1的方案,首先有x*dp[i][0],即这位填0..x-1乘以之后位含49的方案。如果这一位大于4,我们可以填4,下一位填9。如果这位和之前一位组成了49,那么之后0..之后最大值都是含49的,加上就可以。
具体看代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#define ll long long
#define N 110
using namespace std;
int a[N];
ll dp[N][3];
ll n;
int init()//打表 
{
	dp[0][2]=1;
	for(int i=1;i<=24;i++)
	{
		dp[i][0]=dp[i-1][0]*10+dp[i-1][1];
		dp[i][1]=dp[i-1][1]+dp[i-1][2];
		dp[i][2]=dp[i-1][1]*8+dp[i-1][2]*9;
	}
}
int main()
{
	int t,i,j,k;
	init();
	scanf("%d",&t);
	while(t--)
	{
		int cnt=0;
		scanf("%lld",&n);
		while(n)
		{
			a[cnt++]=n%10;
			n=n/10;
		}
		a[cnt]=0;
		ll ans=0;
		for(int i=cnt-1;i>=0;i--)
		{
			if(!a[i])
				continue;
			ans+=dp[i][0]*a[i];
			if(a[i]>4)
				ans+=dp[i][1];
			if(a[i+1]==4&&a[i]==9)
			{
				ll tmp=0;
				for(int j=i-1;j>=0;j--)
					tmp=tmp*10+a[j];
				ans+=tmp+1;
				break;
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}


你可能感兴趣的:(hdoj Bomb 3555 (数位DP)好题)