这也是一道数位dp的题。
题意:
让你在1~N中间找出含有“49”的数有几个,并输出。
思路:
这一开始我想着和上一题一样,正着枚举,但是发现这样子不太方便,后来借鉴了别人的思路发现我们可以反着做,先找出不含有49的数有几个,然后用N减掉就好了。这里还包含了0,所以记得要加上1。
*然后dp[dep][pre]记得要开LL,要不然会WA。
#include<cstdio>
#include<cstring>
#include<map>
#include<set>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<iostream>
#include<time.h>
using namespace std;
typedef __int64 ll;
typedef unsigned __int64 ULL;
#define pi acos(-1.0)
#define Ex exp(1.0)
#define maxn 66
int dig[maxn],vis[maxn][maxn];
ll dp[maxn][maxn]; //要用__int64存!
ll go(int dep,int pre,int less){
if(dep<0) return 1;
else if(vis[dep][pre]&&less) return dp[dep][pre];
else{
if(less){
ll& tmp=dp[dep][pre];
vis[dep][pre]=1;
for(int i=0;i<10;i++){
if(pre!=4||(pre==4&&i!=9)){
tmp+=go(dep-1,i,1);
}
}
return tmp;
}
else{
ll tmp=0;
for(int i=0;i<=dig[dep];i++){
if(pre!=4||(pre==4&&i!=9)){
tmp+=go(dep-1,i,i!=dig[dep]);
}
}
return tmp;
}
}
}
ll solve(ll x){
int len=0;
while(x){
dig[len++]=x%10;
x=x/10;
}
return go(len-1,0,0); //!!!反着做的思路
}
int main(){
ll n;
int T;
while(~scanf("%d",&T)){
while(T--){
scanf("%I64d",&n);
printf("%I64d\n",n-solve(n)+1); //因为它把0也给算进去了,所以最后要加上1
}
}
#ifndef ONLINE_JUDGE
system("pause");
#endif
return 0;
}
/*
3
1
50
500
*/