http://acm.hdu.edu.cn/showproblem.php?pid=3555
dp[i][0]代表[i+1,n-1]位上没出现过49且第i+1位上的数不是4
dp[i][1]代表[i+1,n-1]位上没出现过49但第i+1位上的数是4
dp[i][2]代表[i+1,n-1]位上已出现过49
using namespace std;
typedef long long ll;
const int maxn=50;
ll dp[maxn][5];
int bit[maxn];
ll dfs(int pos,int sta,int limit)
{
ll res;
int up,i;
if(pos==-1) return sta==2;
if(!limit&&dp[pos][sta]!=-1) return dp[pos][sta];
if(!limit) up=9;
else up=bit[pos];
res=0;
for(i=0;i<=up;i++){
if(i==4) res+=dfs(pos-1,max(sta,1),limit&&i==bit[pos]);
else if(i==9) res+=dfs(pos-1,sta==1?2:sta,limit&&i==bit[pos]);
else res+=dfs(pos-1,sta==2?2:0,limit&&i==bit[pos]);
}
if(!limit) dp[pos][sta]=res;
return res;
}
ll solve(ll val)
{
int pos;
pos=0;
while(val>0){
bit[pos++]=val%10;
val/=10;
}
return dfs(pos-1,0,1);
}
int main()
{
ll n;
int t;
memset(dp,-1,sizeof(dp));
scanf("%d",&t);
while(t--){
scanf("%lld",&n);
printf("%lld\n",solve(n));
}
return 0;
}
其实可以反面考虑 即求不含49的数
using namespace std;
ll dp[30][2];
ll num[30];
ll solve(ll n);
ll dfs(int step,int pre,int sta,int lim);
int main()
{
ll n,sum;
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld",&n);
printf("%lld\n",n-solve(n)+1);
}
return 0;
}
ll solve(ll n)
{
int i,p;
i=0;
while(n>0)
{
num[++i]=n%10;
n/=10;
}
memset(dp,-1,sizeof(dp));
return dfs(i,0,0,1);
}
ll dfs(int step,int pre,int sta,int lim)
{
ll ans;
int up,i;
if(step==0) return 1;
if(lim==0&&dp[step][sta]!=-1) return dp[step][sta];
if(lim==1) up=num[step];
else up=9;
ans=0;
for(i=0;i<=up;i++)
{
if(pre==4&&i==9) continue;
ans+=dfs(step-1,i,i==4,lim==1&&i==num[step]);
}
if(lim==0) dp[step][sta]=ans;
return ans;
}