一本通1589:不要 62
原题链接
写在前面:在校内oj一次模拟赛中有这道题,在洛谷上找了找,结果没有,没想到在一本通上找到了
数位dp
数位dp裸题
不多说了,直接上代码吧(有注释)
不会真的有人写数位dp不用深搜吧QWQ
#include <bits/stdc++.h>
using namespace std;
int l, r, len;
int num[15], dp[15][15][2]; //dp[len][pre][lim] 解释见下
int dfs(int len, int pre, int lim){ //len:倒着处理到第len位(实际上对于x是正着处理每一位)。pre:上一位是几(判断62)。lim:是否有上界
if(!len) return 1; //处理完了,返回1
if(dp[len][pre][lim] != -1) return dp[len][pre][lim]; //记忆化
int res = lim ? num[len] : 9; //找出上界
int ans = 0;
for(int i = 0; i <= res; i++){
if(i == 4 || (pre == 6 && i == 2)) continue; //根据题意判断
ans += dfs(len - 1, i, lim && (i == res)); //正常搜索
}
return dp[len][pre][lim] = ans;
}
int solve(int x){
len = 0;
while(x){
num[++len] = x % 10; //注意这里是倒着存x的每一位,看到这里后可以再去理解一下上面的len
x /= 10;
}
memset(dp, -1, sizeof(dp)); //注意dp数组初值-1,因为有许多情况dp值为0,无法判断是否计算过
return dfs(len, 0, 1); //刚开始第一位就有上界,所以lim初值为1
}
int main(){
while(scanf("%d%d", &l, &r) && l && r)
printf("%d
", solve(r) - solve(l - 1)); //利用前缀和思想,计算答案
return 0;
}