题目连接
会有很多做法,本菜渣现在只会这一种,如果你有什么好的做法请留下链接。 本菜渣也会持续更新
//带记忆数组
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
int a[30];
long long dp[30][2][2][2];//下标 数位 four nine limit
long long dfs(int pos,int four,int nine, int limit)
{
if( nine&&four&&pos== -1)return 1;//只有 前面有49才统计数
else if(pos == -1)
{
return 0;
}
if(dp[pos][four][nine][limit]!= -1)return dp[pos][four][nine][limit];
long long re = 0;
int up;//上限
up = limit?a[pos]:9;//判断上限为哪个
for(int i = 0;i <= up;i++)//循环该位可能出现的数
{
if(four&&nine)re+= dfs(pos-1, true,true, limit&&a[pos] == i);//如果之前出现49 后面的数不管是什么 都符合题意
else if(four)//上一个是4的情况
{
if(i == 9)re+=dfs(pos-1, true,true, limit&&a[pos] == i);//如果上一个是4这一个是9 后面不管是什么肯定符合题意
else re+=dfs(pos-1, i == 4,false, limit&&a[pos] == i);// 否则 就重新判断 判断该数是否是4
}
else //上一个不是4的情况
{
re+=dfs(pos-1, i==4,false ,limit&&a[pos] == i);//重新判断该数是否是4
}
}
return dp[pos][four][nine][limit] = re;
}
long long solve(long long x)//拆分函数
{
memset(dp , -1, sizeof(dp));
int len = 0;
while(x)
{
int m = x%10;
x/=10;
a[len++] = m;
}
return dfs(len-1, false,false, true);
}
int main()
{
int n;
cin>>n;
while(n--)
{
ll m;
scanf("%lld", &m);
cout<<solve(m)<<endl;
}
return 0;
}