【DP练习】Bomb(HDU3555)
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?
给一个数N,要求1到N中,数位中出现连续的49的数有多少个,比如49,149,249,499之类的。
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
- 思路和某些题解不同(用总个数减不包含的个数)
- 不包含个数的求法:https://www.cnblogs.com/wuwendongxi/p/13298890.html
- define long long
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#define int long long
using namespace std;
long long m;
int b[50],dp[50][3],n;
int dfs(int x,int y,int flag)
{
if(x==1) return 1;
if(!flag&&dp[x][y]!=-1) return dp[x][y];
int count=flag?b[x-1]:9,ans=0;
for(int i=0;i<=count;++i)
{
if((y==1&&i==9)) continue;
ans+=dfs(x-1,i==4?1:0,flag&&i==count);
}
return flag?ans:dp[x][y]=ans;
}
int start(long long x)
{
int len=0;
for(;x;x/=10) b[++len]=x%10;
for(int i=0;i<=len+1;++i) dp[i][0]=dp[i][1]=-1;
return dfs(len+1,0,1);
}
signed main()
{
scanf("%lld",&n);
for(int i=1;i<=n;++i) scanf("%lld",&m),printf("%lld\n",m-start(m)+1);
return 0;
}
另附思路2(大众):
- dp[i][j]表示 当前为第 i 位,状态为j的在范围内,不是边界上,符合条件 数字的个数
- j=1表示上一位出现4,j=2表示第1到i-1位出现49,否则为j=0。
核心代码:
LL dfs(int i,int j,int flag)
{
if(i==1) return j==2;
if(!flag && dp[i][j]!=-1) return dp[i][j];
int bound=flag? lim[i-1]:9;
LL ret=0;
for(int k=0;k<=bound;k++)
{
if(j==2) ret+=dfs(i-1,2,flag&& k==bound);
else if(k==9 && j==1) ret+=dfs(i-1,2,flag && k==bound);
else if(k==4) ret+=dfs(i-1,1,flag && k==bound);
else ret+=dfs(i-1,0,flag && k==bound);
}
return flag? ret:dp[i][j]=ret;
}