最近在补全提高课所有题目的题解,宣传一下汇总的地方提高课题解补全计划
数位DP基础概念 指路:【数位DP基本概念+数位DP记忆化搜索】
题目描述
给定正整数区间 $[l, r]$,求该区间内 单独数位上 没有 $4$ 且 相邻数位上 没有 $62$ 的数字个数
分析
想了解 数位DP 基础概念的,可以看一下最上面我贴的链接,这里不会对 重复内容 进行额外讲解
把求 一段区间 的问题,转化为求两个 前缀区间 的问题
本题参数 $st$ 需要记录的参数是:前一位数字是什么
这样就能有效 排除 枚举 $62$ 的情况,而枚举 $4$ 的情况直接 特判 即可
具体请看代码部分(同样我推荐在看过以上思路以后自己先手写一遍,调不出来在看代码,思路不难
Code
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 35;
int l, r;
int a[N], al;
int f[N][N];
int dp(int pos, int st, int op)
{
if (!pos) return 1;
if (!op && ~f[pos][st]) return f[pos][st];
int res = 0, maxx = op ? a[pos] : 9;
for (int i = 0; i <= maxx; i ++ )
if (i != 4 && (st != 6 || i != 2))
res += dp(pos - 1, st == -1 && !i ? -1 : i, op && i == a[pos]);
return op && st == -1 ? res : f[pos][st] = res;
}
int calc(int x)
{
memset(f, -1, sizeof f); al = 0;
for ( ; x; x /= 10) a[ ++ al] = x % 10;
return dp(al, -1, 1);
}
int main()
{
while (cin >> l >> r, l || r)
{
cout << calc(r) - calc(l - 1) << endl;
}
return 0;
}
csdn的博客
数据是1e9 感觉N=10足够了啊
int
范围内十进制开10位够了,二进制要开31位,我的板子就统一了一下,反正不会爆掉大佬,为什么N=35?
int
范围内十进制开 $10$ 位够了,但是二进制要开 $31$ 位原版:
改成
那为什么还要特判一下呢