hdu3555数位dp
来源:互联网 发布:蕲春广电网络 编辑:程序博客网 时间:2024/05/02 02:36
Bomb
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 4063 Accepted Submission(s): 1403
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?
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.
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
3150500
Sample Output
0115HintFrom 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.题意:求0-n中出现了多少个含有49的数字。小结:第一次做数位dp的题,对数位dp的一般模式有了一些了解,不过还是有很多地方没搞懂,dp的初始化,这里为什么n要++,为什么以i开始的时候,后面呢能取到所有出现49的情况等等。代码:#include<iostream>#include<vector>#include<string>#include<queue>#include<map>#include<cstdio>#include<cstring>#define maxn 2005#define ll unsigned long long#define INF 0xfffffffusing namespace std;int digit[25];ll dp[25][3];//dp[i][0]表示长度为i不出现49的数字个数//dp[i][1]表示长度为i以9开头不出现49的数字个数//dp[i][2]表示长度为i出现49的数字个数void init(){ memset(dp,0,sizeof(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]=dp[i-1][1]+10*dp[i-1][2]; }}int main(){ int t; ll n,ans; init(); cin>>t; while(t--) { ans=0; cin>>n; n++;//不理解为什么要++ //求出n的每个数位 int cnt=0; memset(digit,0,sizeof(digit)); while(n) { digit[++cnt]=n%10; n/=10; } int flag=0;//标记是否前面出现过49 for(int i=cnt;i>=1;i--) { ans+=digit[i]*dp[i-1][2];//i-1位含有49 不理解这里有可能以digit[i]开头的,后面的所有dp[i-1][2]情况不是都取的到 if(flag) { ans+=digit[i]*dp[i-1][0];//i-1位不含有49 这里也是 } if(flag==0&&digit[i]>4) { ans+=dp[i-1][1]; } if(digit[i]==9&&digit[i+1]==4) flag=1; } cout<<ans<<endl; }return 0;}第二种做法:标准的记忆化搜索今天大强给我讲了下划状态图,说dp的题都可以这种方法来做,一般状态图画出来的话就好些状态转移方程。这题在花状态图的时候用了四个标记变量:pos记录当前的位置,pre记录上一个位置的数字,flag记录是否出现过49,limit记录是否受限制,就是能否取到9.代码:#include<iostream>#include<cstring>#define ll __int64using namespace std;int digit[25];ll dp[25][10][3];//dp记录的是没有限制的情况下的状态ll dfs(int pos,int pre,int flag,int limit){ if(pos==-1) return flag==1;//如果已经遍历完n,最后一个数字是否为含有49的数字看flag if(!limit&&dp[pos][pre][flag]!=-1) return dp[pos][pre][flag]; ll sum=0; int end=(limit?digit[pos]:9); for(int i=0;i<=end;i++) { if(pre==4&&i==9) sum+=dfs(pos-1,i,1,limit&&i==end);//受限制的条件是前面的所有位都是取最大的 else sum+=dfs(pos-1,i,flag,limit&&i==end); } if(!limit) dp[pos][pre][flag]=sum; return sum;}ll work(ll n){ int cnt=0; while(n) { digit[cnt++]=n%10; n/=10; } memset(dp,-1,sizeof(dp)); ll ans=dfs(cnt-1,-1,0,1); return ans;}int main(){ int t; ll n; cin>>t; while(t--) { cin>>n; cout<<work(n)<<endl; } return 0;}
- 【数位DP】 hdu3555 Bomb
- 【hdu3555】【数位DP】Bomb
- 【数位DP】Bomb HDU3555
- hdu3555 Bomb 数位DP
- hdu3555数位dp
- 数位dp hdu3555
- HDU3555:Bomb(数位DP)
- hdu3555 Bomb (数位DP)
- HDU3555 Bomb 数位DP
- hdu3555 数位DP
- hdu3555(数位DP)
- Hdu3555 - Bomb - 数位dp
- hdu3555 Bomb 数位dp
- hdu3555 Bomb(数位DP)
- HDU3555 Bomb 数位DP
- hdu3555,hdu2089 数位dp
- hdu3555(数位DP)
- hdu3555 数位dp
- Android使用SQlite数据库
- TextView 字体水平滚动,走马观灯 和 间距设置
- 搭建基于Jenkins+SVN+Maven持续集成环境(CI)
- lua学习笔记2(require 和程序加载流程)
- 关于mysql处理百万级以上的数据时如何提高其查询速度的方法
- hdu3555数位dp
- JS 对输入框进行限制
- hdu1312(DFS Red and Black )
- 利用矩阵求解fibonacci数列 时间复杂度为O(lgn)
- 深入理解Hadoop集群和网络
- c# xml
- java 的异常处理
- Hadoop DataNode不能正常工作的原因
- Oracle:查找表的主键,外键,唯一性约束,索引