题目链接:[kuangbin带你飞]专题十五 数位DP D - Bomb
题意
求1~n的范围里含有49的数字的个数。
思路
记忆化搜索
dfs(len, pre, flag)
len表示当前位数
pre==0 不含49且上一位不为4
pre==1 不含49且上一位为4
pre==2 含49
flag表示是否可以任意取值(判断范围)。
即可。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
#define LL long long
LL dp[20][3];
int dis[20];
LL dfs(int len, int pre, bool flag)
{
if(len < 0)
return pre==2;
if(!flag && dp[len][pre]!=-1)
return dp[len][pre];
int end = flag?dis[len]:9;
LL ans = 0;
for(int i=0; i<=end; i++)
{
if(pre==2 || pre==1 && i==9)
ans += dfs(len-1, 2, flag&&i==end);
else if(i==4)
ans += dfs(len-1, 1, flag&&i==end);
else
ans += dfs(len-1, 0, flag&&i==end);
}
if(!flag)
dp[len][pre] = ans;
return ans;
}
LL solve(LL n)
{
int len = 0;
while(n)
{
dis[len++] = n%10;
n /= 10;
}
return dfs(len-1, 0, 1);
}
int main()
{
int T;
cin>>T;
memset(dp, -1, sizeof(dp));
while(T--)
{
LL n;
cin>>n;
cout<<solve(n)<<endl;
}
return 0;
}