【数位DP】【P2657】[SCOI2009]windy数
Description
windy定义了一种windy数。不含前导零且相邻两个数字之差至少为 的正整数被称为windy数。 windy想知道,
在 和 之间,包括 和 ,总共有多少个windy数?
Limitation
Solution
前天重写这个题,换了一种比较好写的DP方式,这里记下来。
考虑由于前导 和顶上界都最多可能有 中方案,因此直接使用一个 bool 变量记录即可。
设 是考虑前 位,第 位是 且不顶上界的方案数,这样的转移就非常好写了。、
Code
#include <cmath>
#include <cstdio>
#include <cstring>
const int maxn = 100;
int x, y;
int A[maxn], B[maxn];
ll frog[maxn][10];
int ReadNum(int *p);
ll calc(const int *const num, const int n);
int main() {
freopen("1.in", "r", stdin);
int x = ReadNum(A); y = ReadNum(B);
for (int i = x - 1; ~i; --i) {
if ((--A[i]) >= 0) {
break;
} else {
A[i] = 9;
}
}
if (A[x] == 0) { --x; }
qw(calc(B, y) - calc(A, x), '\n', true);
return 0;
}
int ReadNum(int *p) {
auto beg = p;
do *p = IPT::GetChar() - '0'; while ((*p < 0) || (*p > 9));
do *(++p) = IPT::GetChar() - '0'; while ((*p >= 0) && (*p <= 9));
return p - beg;
}
ll calc(const int *const num, const int n) {
if (n <= 1) {
return num[0];
}
memset(frog, 0, sizeof frog);
bool upc = true;
for (int i = 1; i < num[0]; ++i) {
frog[0][i] = 1;
}
for (int i = 1; i < n; ++i) {
int di = i - 1;
for (int j = 0; j < 10; ++j) {
for (int k = 0; k < 10; ++k) if (abs(j - k) >= 2) {
frog[i][j] += frog[di][k];
}
++frog[i][j];
}
--frog[i][0];
if (upc) {
for (int k = 0; k < num[i]; ++k) if (abs(num[di] - k) >= 2) {
++frog[i][k];
}
if (abs(num[di] - num[i]) < 2) {
upc = false;
}
}
}
ll _ret = 0;
for (int i = 0, dn = n - 1; i < 10; ++i) {
_ret += frog[dn][i];
}
return _ret + upc;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)