题目链接:hdu 2089
这两道虽然是数位dp的水题,但是hdu 3555 我可是调试了很久啊~~~最后才发现是中间变量我开成了int,成功的爆掉了!!!我不是用递推写的,我写的是记忆化搜索,我个人认为记忆化搜索好写且易理解(果然是我太弱了= =)。
hdu 2089:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int N,M;
int dp[100005][3],limit[100000+5];
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int dfs(int l,int now,int fp){
if(!l)return 1;
if(!fp && dp[l][now]!=-1)return dp[l][now];
int tot=0; int lmax=fp?limit[l]:9;
for(int i=0;i<=lmax;i++){
if(i==4 || (now && i==2))continue;
tot+=dfs(l-1,i==6,fp && i==lmax);
}
if(!fp)dp[l][now]=tot;
return tot;
}
int find(int x){
int len=0;
while(x){
limit[++len]=x%10; x/=10;
}
return dfs(len,false,true);
}
int main(){
memset(dp,-1,sizeof(dp));
while(1){
N=read(); M=read();
if(N==0&&M==0)break;
printf("%d\n",find(M)-find(N-1));
}
return 0;
}
hdu 3555:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int limit[100];
long long N;
long long dp[100][5];
inline long long read(){
long long x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
long long dfs(int l,int now,int fp){//now=0上位非4,=1上位为4
if(!l)return 1;
if(!fp && dp[l][now]!=-1)return dp[l][now];
long long tot=0; int lmax=fp?limit[l]:9;//就是tot爆了!
for(int i=0;i<=lmax;i++){
if(now && i==9)continue;
tot+=dfs(l-1,i==4,fp && i==lmax);
}
if(!fp)dp[l][now]=tot;
return tot;
}
long long find(long long x){
int len=0;
while(x){
limit[++len]=x%10; x/=10;
}
return dfs(len,0,1);
}
int main(){
memset(dp,-1,sizeof(dp));
long long T=read();
while(T--){
N=read();
printf("%I64d\n",N-(find(N)-find(0)));
}
return 0;
}