hdu 3555 Bomb 2010 ACM-ICPC Multi-University Training Contest 12
来源:互联网 发布:网络商标注册费用 编辑:程序博客网 时间:2024/04/28 10:01
为了让智硬的自己以后还能看懂,尽量写详细点><
数位DP是按位考虑状态,然后再涉及到每一位数字的大小关系。
这里面用dp[i][0]表示i位数不包含49的个数,dp[i][1]表示i位数不包含49的但是以9开头的个数,dp[i][2]表示i位数包含49的个数,注意dp[i][0]包含了dp[i][1],最后枚举的时候不要算重了。
这里面的递推关系是从后i-1位推到后i位,新加的第i位的数位于高位。这里面的dp[i][j]是整个i位数所有数中有没有49,在下面的状态转移过程中还会根据input number每一位数的大小进行更新。
举个例子就可以找出递推关系:
_X49XX->XX49XX
_9XXXX->49XXXX
_XXXXX->9XXXX or XXXXX
因为新加的第i位可以填0-9共十个数,因此:
dp[i][0]=dp[i-1][0]*10-dp[i-1][1];//要减去49XXX的casedp[i][1]=dp[i-1][0];//直接在最高位填上9dp[i][2]=dp[i-1][2]*10+dp[i-1][1];//要加上49XXX的case
后面的递推是从高位往低位推,智硬的我想了好久=。= 最后发现举个例子一目了然(⊙o⊙)…可见动手写一写还是比瞎想有作用,上次比赛要是多画几个sample那一题公式弄不好就弄出来了><
for example, n=5673
i=4:
0~4 [后面的数包含49]
4 [后面的数不包含49但是以9开头]
注意这里面最高位没有考虑5,因为dp[3][0 or 1 or 2]考虑的是0-999里面的数,所以这一位考虑5可能就会包含超出n的case
i=3:
5 0~5 [后面的数包含49]
54 [后面的数不包含49但是以9开头]
i=4的位置没有填5,所以i=3时在i=4处填的是5,因此不同的i对应的是disjoint sample space,所以最后的ans要加起来。
i=2:
5 60~6 [后面的数包含49]
5 64 [9XXXX]
i=1:
5 6 70~2 [XXX49XX]
由此可见,枚举的上界不会达到,最后枚举的只考虑了0~n-1的case,所以最初要n++。
然后要注意ans要设成long long,最后的数真心会很大(预处理的dp都出现了负的==)
#include<iostream>#include<stdio.h>#include<cstdio>#include<stdlib.h>#include<vector>#include<string>#include<cstring>#include<cmath>#include<algorithm>#include<stack>#include<queue>#include <ctype.h>using namespace std;int T;long long N;const int maxn=20;long long dp[maxn][3];int digit[maxn];long long ans;int len;void initial(){ memset(dp,0,sizeof(dp)); dp[0][0]=1;//0位数(null)不为49有一种方案,空方案作为一种方案 dp[0][1]=0; dp[0][2]=0; for(int i=1;i<maxn;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]; //cout<<dp[i][0]<<" "<<dp[i][1]<<" "<<dp[i][2]<<endl; }}void getdigit(){ len=0; memset(digit,0,sizeof(digit)); N++; memset(digit,0,sizeof(digit)); while(N>0) { digit[++len]=N%10; N/=10; }}void DP(){ ans=0;//为什么ANS要加起来? bool flg=false; int last=0; for(int i=len;i>=1;i--) { ans+=dp[i-1][2]*digit[i];//如果后面的数包含49,这一位填什么数都无所谓,只要比N小 // cout<<" 1 "<<i<<" "<<ans<<endl; if(flg)//如果高位出现过49(不一定是紧邻的前两位),后面可以填没有49的数 { ans+=dp[i-1][0]*digit[i]; //flg=false; // cout<<" 2 "<<i<<" "<<ans<<endl; } if(!flg&&digit[i]>4)// 如果前面没有49,第i位可以填4,后面接以9开头的数。 {//并且必须!flg才可以执行,因为dp[i][0]包含了dp[i][1]的case,所以前面出现过49,上一步已经包含了第i位填4,后面接以9开头的数的case。 ans+=dp[i-1][1]; // cout<<" 3 "<<i<<" "<<ans<<endl; } if(last==4&&digit[i]==9) { flg=true; } last=digit[i]; } printf("%I64d\n",ans);}int main(){ freopen("input.txt","r",stdin); // freopen("data.txt","r",stdin); //freopen("out1.txt","w",stdout); scanf("%d",&T); initial(); for(int i=0;i<T;i++) { scanf("%I64d",&N); getdigit(); DP(); } return 0;}
- hdu 3555 Bomb 2010 ACM-ICPC Multi-University Training Contest 12
- hdu3555 - Bomb(2010 ACM-ICPC Multi-University Training Contest(12))数位dp
- Print Article[HDU 3507,2010 ACM-ICPC Multi-University Training Contest]
- hdu 3496 Watch The Movie //2010 ACM-ICPC Multi-University Training Contest(6)——Host by BIT
- hdu 3491 Thieves //2010 ACM-ICPC Multi-University Training Contest(6)——Host by BIT
- HDU 3488 Tour //2010 ACM-ICPC Multi-University Training Contest(6)——Host by BIT
- HDU 3602 2012(2010 ACM-ICPC Multi-University Training Contest(16)——Host by NUDT)
- 2010 ACM-ICPC Multi-University Training Contest(1) ——A Task Process
- 2010 ACM-ICPC Multi-University Training Contest(5)HDU3485Count 101题解动态规划DP
- 2010 ACM-ICPC Multi-University Training Contest(14)——Host by BJTU
- SPY //2010 ACM-ICPC Multi-University Training Contest(10)——Host by HEU
- Tree //2010 ACM-ICPC Multi-University Training Contest(10)——Host by HEU
- Subsequence //2010 ACM-ICPC Multi-University Training Contest(10)——Host by HEU
- Max Angle //2010 ACM-ICPC Multi-University Training Contest(10)——Host by HEU
- Computer Assembling //2010 ACM-ICPC Multi-University Training Contest(10)——Host by HEU
- 2010 ACM-ICPC Multi-University Training Contest(11)——Host by BUPT
- 2010 ACM-ICPC Multi-University Training Contest(2)——Host by BUPT
- HDU 3605 Escape 最大流or二分图多重匹配 2010 ACM-ICPC Multi-University Training Contest(17)——Host by ZSTU
- Java初学习 - Arrays.asList方法总结
- 第13周项目5-字符串操作-(1.2)
- HDU5109 Alexandra and A*B Problem(数学题)
- 【Unity3D】【NGUI】如何给Clipping的Panel下的UITexture加shader
- 《JAVA与模式》之不变模式
- hdu 3555 Bomb 2010 ACM-ICPC Multi-University Training Contest 12
- mongodb 批量查询 输出指定字段
- linux man 命令的使用方式 与 man 命令的解释
- JVM实用参数(一)JVM类型以及编译器模式
- 第十三周上机项目五2.2
- 初识SQL数据库之事务
- 【Android 开发】: Android 消息处理机制之二: Message 中 obtain()源代码剖析
- 第十三周项目数组的降序排列
- 音视频的数据格式详解