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
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=50;
ll dp[maxn][3];
int bit[maxn];
ll dfs(int pos,int pre,int sta,int limit)
{
ll res;
int up,i,tmp;
if(pos==-1){
return sta==2;
}
if(!limit&&dp[pos][sta]!=-1){
return dp[pos][sta];
}
if(limit) up=bit[pos];
else up=9;
res=0;
for(i=0;i<=up;i++){
if(i==4){
tmp=max(1,sta);
}
else if(i==9){
if(pre==4) tmp=2;
else tmp=sta;
}
else{
if(sta==2) tmp=2;
else tmp=0;
}
res+=dfs(pos-1,i,tmp,limit&&i==bit[pos]);
}
if(!limit) dp[pos][sta]=res;
return res;
}
ll solve(ll val)
{
int n;
n=0;
while(val>0){
bit[n++]=val%10;
val/=10;
}
return dfs(n-1,-1,0,1);
}
int main()
{
ll val;
int t;
memset(dp,-1,sizeof(dp));
scanf("%d",&t);
while(t--){
scanf("%lld",&val);
printf("%lld\n",solve(val));
}
return 0;
}
其实可以反面考虑 即求不含49的数
#include <bits/stdc++.h>
using namespace std;
#define ll long long
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;
}