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?
InputThe 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.
Now the counter-terrorist knows the number N. They want to know the final points of the power. Can you help them?
The input terminates by end of file marker.
OutputFor each test case, output an integer indicating the final points of the power.Sample Input
3 1 50 500Sample Output
0
1
15
Hint
From 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.
分析:
刚开始学习数位dp,这是做的第2道题,第一道是:不要62
分析一下“要”和“不要”的区别吧:
“不要”:则把不符合我们要得数的情况给跳过(6和2连续出现,和含有4的情况),剩下的就是符合要求的,sta两个状态:1->上一位是6,0->上一位不是6,最后没被跳过的数就是符合要求的,返回1
“要”:此题是要49,设sta三个状态,0->上一位不是4,且没出现49,1->上一位是4,且没出现49,2->出现过49
这样把所有的数过一遍,结束时判断sta值是否为2,是返回1,否返回0。
代码如下:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
typedef long long ll;
int a[20];
ll dp[20][3];
ll dfs(int pos,int sta,int limit){
if(pos==-1)return sta==2;
if(!limit&&dp[pos][sta]!=-1)return dp[pos][sta];
ll tmp=0;
int up=limit?a[pos]:9;
for(int i=0;i<=up;i++){
int now=sta;
if(now!=2){
if(now==1){
if(i==9)now=2;
else if(i==4)now=1;
else now=0;
}
else {
if(i==4)now=1;
}
}
tmp+=dfs(pos-1,now,limit&&i==a[pos]);
}
if(!limit)dp[pos][sta]=tmp;
return tmp;
}
ll solve(ll x){
int pos=0;
while(x){
a[pos++]=x%10;
x/=10;
}
return dfs(pos-1,0,1);
}
int main(){
int t;
ll n;
scanf("%d",&t);
while(t--){
scanf("%lld",&n);
memset(dp,-1,sizeof(dp));
printf("%lld\n",solve(n));
}
}