hdu3555Bomb以及对数位dp的讲解

Bomb

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)

Total Submission(s): 9295    Accepted Submission(s): 3282

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

[email protected]

Source

2010 ACM-ICPC Multi-University Training Contest(12)——Host
by WHU

所谓数位dp就是dp+组合数学

首先是预处理出dp:

dp[i][0]:i位数,不包含49的有几个

dp[i][1]:i位数,不包含49但是以9开头的有几个

dp[i][2]:i位数,包含49的有几个

(i位数包含0开头的情况)

组合数学部分:

算1到x有几个数自己含有49时,

为了方便描述,用一个串s储存x,其中0为起始位置,串长为len,

s[i]到s[len-1]组成一个数字y,算出数字恰有len-i位,且不大于y时,且自己含有49的有多少个

枚举所有i,累加即可

注意:

当49已经在之前出现时,要特殊处理

若x本身含有49,记得算上x本身

y可以是0开头,因为若每次都这样,是不会算多的,相当于每次都把下一次的i算了一些情况

#include<map>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<climits>
#include<list>
#include<iomanip>
#include<stack>
#include<set>
using namespace std;
typedef long long ll;
ll dp[20][3];
ll work(string s)
{
	int len=s.length();
	ll ans=0;
	bool flag=0;
	for(int i=0;i<len;i++)
	{
		if(flag)
			ans+=(dp[len-i-1][0]+dp[len-i-1][2])*(s[i]-'0');
		else
		{
			ans+=dp[len-i-1][2]*(s[i]-'0');
			if(s[i]>'4')
				ans+=dp[len-i-1][1];
		}
		if(!flag&&i>0&&s[i-1]=='4'&&s[i]=='9')
			flag=1;
	}
	if(flag)
		ans++;
	return ans;
}
int main()
{
	dp[0][0]=1;
	for(int i=1;i<19;i++)
	{
		dp[i][0]=dp[i-1][0]*10-dp[i-1][1];
		dp[i][1]=dp[i-1][0];
		dp[i][2]=dp[i-1][2]*10+dp[i-1][1];
	}
	int T;
	cin>>T;
	while(T--)
	{
		string s;
		cin>>s;
		cout<<work(s)<<endl;
	}
}
时间: 2024-11-03 22:36:54

hdu3555Bomb以及对数位dp的讲解的相关文章

Hdu3555Bomb数位dp

含有49的 ..就是不要49 ..也可以直接搞 #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #include <

【10.17校内测试】【二维数位DP】【博弈论/预处理】【玄学(?)DP】

Solution 几乎是秒想到的水题叻! 异或很容易想到每一位单独做贡献,所以我们需要统计的是区间内每一位上做的贡献,就是统计区间内每一位是1的数的数量. 所以就写数位dp辣!(昨天才做了数字统计不要太作弊啊!) Code #include<bits/stdc++.h> #define LL long long #define mod 1000000007 using namespace std; inline void read(LL &x) { x = 0; char ch = g

数位dp详解

哈哈哈,本菜鸡经过长时间研究,终于略懂的这看似神奇的数位dp... 数位dp,顾名思义就是数位+dp,数位即是一个数的每一位上的数字,dp也就是动态规划了. 首先来讲在何时应该想到要用数位dp吧.(相信大部分人都是为了做题而学的) 数位dp的题目一般都是给定一个区间,如[l , r],然后叫你求在这区间里的数有多少个符合题目给的限制条件(解题时一般都是运用前缀和求解,即[l , r]=[0 , r]-[0 , l-1].) 其次就是讲解数位dp的原理和模板代码了.(菜鸡的我不知道讲的好不好,尽量

数位dp小练

最近刷题的同时还得填填坑,说来你们也不信,我还不会数位dp. 照例推几篇博客: 数位DP讲解 数位dp 的简单入门 这两篇博客讲的都很好,不过代码推荐记搜的形式,不仅易于理解,还短. 数位dp的式子一般是这样的:dp[i][][]表示到第\(i\)位,而后面几维就因题而异了. 不过通用的思想就是利用前缀相减求出区间信息. 算了上题吧. [SCOI2009]windy数 这都说是数位dp入门题. 根据这题,受到影响的数只有相邻两个,因此dp[i][j]表示到第\(i\)位(从高往低)上一位的数\(

51Nod 1009 数字1的个数 | 数位DP

题意: 小于等于n的所有数中1的出现次数 分析: 数位DP 预处理dp[i][j]存 从1~以j开头的i位数中有几个1,那么转移方程为: if(j == 1) dp[i][j] = dp[i-1][9]*2+pow(10,i-1);else dp[i][j] = dp[i-1][9]+dp[i][j-1]; 然后注意下对于每个询问统计的时候如果当前位为1需要额外加上他后面所有位数的个数,就是n%pow(10,i-1); 这样总复杂度log(n)*10 #include <bits/stdc++.

HDU 3555 Bomb (数位DP)

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数,它是按位来进行计数统计的,可以保存子状态,速度较快.数位dp做多了后,套路基本上都差不多,关键把要保存的状态给抽象出来,保存下来. 简介: 顾名思义,所谓的数位DP就是按照数字的个,十,百,千--位数进行的DP.数位DP的题目有着非常明显的性质: 询问[l,r]的区间内,有多少的数字满足某个性质 做法根据前缀和的思想,求出[0,l-1]和[0,r]中满足性质的数的个数,然后相减即可. 算法核心: 关于数位DP,貌似写法还是

51nod1043(数位dp)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1043 题意:中文题诶- 思路:数位dp 我们用dp[i][j]来存储长度为2*i且一半和为j的所有情况(包括前导0的情况),为了方便我们现在只讨论其一半的和的情况,因为如果包括前导0的话其两边的情况是一样的: 我们假设再长度为i-1的数字最前面加1位数字k,0<=k<=9(这位数字加在哪里并不影响答案,因为我们在计算i-1长度的时候已经计算了所有组合情况,

数位dp

1.[hdu3709]Balanced Number 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cstdlib> 6 #include<algorithm> 7 #include<ctime> 8 #include<cmath> 9 #include<queue>

【HDU 3652】 B-number (数位DP)

B-number Problem Description A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string "13" and can be divided by 13. For example, 130 and 2613 are wqb-numbers, but 143 and 2639 are not. Your task