一道数位DP的入门题,很早之前ZB大爷就教过我们 但是那时候一直WA过不去而且代码写的很难看。今天借鉴了一下网上的代码,用DFS来写非常简洁,而且不容易出错。还是非常好的。其实就是一个记忆化搜索的过程。
AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int dp[10][2],num[10]; //dp[i][0]代表长度为i且首位不是6的数
//dp[i][1]代表长度为i且首位是6的数
int dfs(int len,int state ,int pd){
if(len == 0)return 1;
if(pd == 0 && dp[len][state]!=-1) //最高位与要查询的数不同,且dp[len][state]算过,直接返回答案
return dp[len][state];
int ans = 0, k = pd?num[len]:9; //前面如果都相同,这位要比num[len]小,否则就是0~9
for(int i=0;i<=k;i++){
if(i == 4 || (state&&i == 2))continue;//排除不行的
ans += dfs(len-1,i==6,pd&& i == k);
}
if(pd == 0) dp[len][state] = ans;
return ans;
}
int cal(int n){ //最终计算出的结果是从1到n中满足条件的数
int len = 0;
while(n){
num[++len] = n%10;
n/=10;
}
return dfs(len,0,1);
}
int n,m;
int main()
{
memset(dp,-1,sizeof(dp));
while(scanf("%d%d",&n,&m),n+m){
printf("%d\n",cal(m)-cal(n-1));
}
return 0;
}