HDU 3555 Bomb(数位DP)
来源:互联网 发布:通达信短线决策源码 编辑:程序博客网 时间:2024/05/29 07:00
BombTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 15793 Accepted Submission(s): 5754Problem DescriptionThe 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?InputThe 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.OutputFor each test case, output an integer indicating the final points of the power.Sample Input3150500Sample Output0115HintFrom 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.Authorfatboy_cw@WHUSource2010 ACM-ICPC Multi-University Training Contest(12)——Host by WHURecommendzhouzeyong
初次接触数位dp,内心舒畅,精神愉快。dp初始化的思想和之前的非010串差不多。1.dp[i][0]=10*dp[i-1][0]-dp[i-1][1] 2.dp[i][1]=dp[i-1][0]3.dp[i][2]=10*dp[i-1][2]+dp[i-1][1]1代表没有出现在i之前没用出现49的个数2代表i之前没有出现49可是最高位是9的个数,3代表i之前出现49的个数接下来是我对数位dp的理解:(这里的i之前是i到低位)1.第i位之前没有出现49的数的个数,那就是dp[i-1][0],由于第i位可以填0~9,所以是10*dp[i-1][0],并且当第i位填4的时候,如果第i-1位是之前没用出现49但最高位是9的,那就组成了49,所以不符合,那我们需要减去dp[i-1][1],所以dp[i][0]=10*dp[i-1][0]-dp[i-1][1]。2.第i位填9,排除第i位之前出现过49,还有第i位之前没用出现过49但最高位是9的,所以dp[i[1]=dp[i-1][0]3.第i位之前出现过49,第i位可以填0~9,所以是10*dp[i][2],当第i位填4的时候,我们需要加上第i-1为9的(能与第i位组成49),所以dp[i][2]=10*dp[i-1][2]+dp[i-1][1]计算N的时候,我们是从最高位算到最低位的.(i之前表示i到高位,i之后表示i到低位)从最高位开始:首先呢,当前位符合有49的数的个数为len[i]*dp[i-1][2],这里表示当前位可以填0~len[i]-1,所以为什么是len[i]>4才可以加上dp[i-1][1]组成49,原因就在这里,当len[i]=4时,我们在i位填的是0~3,并没有4。接着判断i之前是否出现过49(这里值*49*i***这样的,我们之前dp是**i**49这样的,要区分开),如果已经有49了,我们就要加上i往低位的没有出现过49的数的个数,即dp[i-1][0]*len[i]。如果没出现49的话,我们就要对当前位讨论,如果len[i]>4的话,我们就要加上dp[i-1][1],这样就可以组成49啦,所以这样的数字个数也要加上。(49***49这样的算一个,所以当前面出现49了,我们就不需要讨论当前为是否大于4,不需要加上len[i]*dp[i-1][1])为什么要讨论len[i+1]==4&&len[i]==9,是因为我们之前讨论是在i之后出现49的情况,可是没有讨论i之后没出现49可是之前出现49的情况,例如496000这样的数字,6之后没有出现49,可是6之前出现过49,那我们就要加上6*dp[i-1][0],以此类推,所以像这样的数我们也要加起来。判断这个条件是否成立,对后续有用。ret+1的原因是: dp的过程是算(1, ret)内出现49的数的个数,这里是不包含ret的,如果ret也刚好包含49,那么我们还要对ret进行讨论,如果ret+1,那样我们算的过程也包含了ret,这样就不用讨论ret啦,这样子是不是方便多了呢。终于写好了,不容易,第一次写这么多字,也希望大家能指出错误,一起学习。
#include<iostream>#include<cstring>#include<cstdlib>#include<algorithm>#include<cctype>#include<cmath>#include<ctime>#include<string>#include<stack>#include<deque>#include<queue>#include<list>#include<set>#include<map>#include<cstdio>#include<limits.h>#define fir first#define sec second#define fin freopen("/home/ostreambaba/文档/input.txt", "r", stdin)#define fout freopen("/home/ostreambaba/文档/output.txt", "w", stdout)#define mes(x, m) memset(x, m, sizeof(x))#define pii pair<int, int>#define Pll pair<ll, ll>#define INF 1e9+7#define Pi 4.0*atan(1.0)#define MOD 1000000007#define lowbit(x) (x&(-x))#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define ls rt<<1#define rs rt<<1|1typedef long long ll;typedef unsigned long long ull;const double eps = 1e-12;const int maxn = 4;using namespace std;inline int read(){ int x(0),f(1); char ch=getchar(); while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f;}ll dp[20][3];int len[20];void init(){ mes(dp, 0); dp[0][0] = 1; for(int i = 1; i < 20; ++i){ dp[i][0] = 10*dp[i-1][0] - dp[i-1][1]; dp[i][1] = dp[i-1][0]; dp[i][2] = 10*dp[i-1][2] + dp[i-1][1]; }}int getlen(ull num){ int t = 0; while(num){ len[++t] = num%10; num = num/10; } return t;}void solve(ull num){ int t = getlen(num); ull res = 0; bool flag = false; for(int i = t; i >= 1; --i){ res += (ull)len[i]*dp[i-1][2]; if(flag){ res += (ull)len[i]*dp[i-1][0]; } if(!flag && len[i] > 4){ res += dp[i-1][1]; } if(4==len[i+1] && 9==len[i]){ flag = true; } } cout << res << endl;}int main(){ int Case; Case = read(); ull ret; init(); while(Case--){ cin >> ret; mes(len, 0); solve(ret+1); } return 0;}
1 0
- HDU 3555 Bomb (数位DP)
- hdu 3555 - Bomb [数位dp]
- hdu 3555 Bomb【数位DP】
- HDU 3555 Bomb (数位DP)
- hdu 3555 Bomb 数位DP
- HDU 3555 Bomb (数位DP)
- hdu 3555 Bomb 数位dp
- [HDU 3555]Bomb[数位DP]
- HDU 3555 Bomb 数位DP
- hdu 3555 Bomb 数位dp
- HDU --3555--Bomb--数位DP
- hdu 3555 Bomb (数位DP)
- 【数位DP】【HDU 3555】Bomb
- hdu 3555 Bomb(数位DP)
- HDU 3555 Bomb(数位dp)
- 数位dp HDU 3555 Bomb
- HDU-3555 Bomb 数位DP
- HDU 3555 Bomb(数位DP)
- HDU1008
- C++中的to_string()函数[C++11支持]
- Jar包混淆后引用报错
- 嵌入式Linux网络编程
- 2016 ccpc(长春站) 一个弱鸡的总结
- HDU 3555 Bomb(数位DP)
- latex表格
- 机器学习简单思想梳理
- SDNU 1311.Binomial Coeffcients 杨辉三角算组合数
- 第5周 项目4 - 数制转换
- 从零开始学习SLAM
- HDU 1004
- 课后作业代码参考
- 数据结构总结