Files
python/TangDou/AcWing/ShuWei/1083.md
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

87 lines
2.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## [$AcWing$ $1083$. $Windy$数](https://www.acwing.com/problem/content/1085/)
### 一、题目描述
$Windy$ 定义了一种 $Windy$ 数:**不含前导零** 且 **相邻两个数字之差至少为 $2$** 的正整数被称为 $Windy$ 数。
$Windy$ 想知道,在 $A$ 和 $B$ 之间,包括 $A$ 和 $B$,总共有多少个 $Windy$ 数?
**输入格式**
共一行,包含两个整数 $A$ 和 $B$。
**输出格式**
输出一个整数,表示答案。
**数据范围**
$1≤A≤B≤2×10^9$
**输入样例1**:
```cpp {.line-numbers}
1 10
```
**输出样例1**:
```cpp {.line-numbers}
9
```
**输入样例2**:
```cpp {.line-numbers}
25 50
```
**输出样例2**:
```cpp {.line-numbers}
20
```
### 二、解题思路
* 使用带前导零参数的模板
* 相邻两个数字:这需要传递前一位数字,以方便进行比较,用$st$代表。
* 差至少为$2$,可以用$abs(st-i)>2$进行判断
* 起始值如何合理?就是传递$st=-2$,这样,当前位就算是$0$,也就满足条件的,可以正常开始运行的逻辑。
### 三、实现代码
```cpp {.line-numbers}
#include <bits/stdc++.h>
using namespace std;
const int N = 15;
int a[N], al;
int f[N][N];
// st代表前一数位上的数值
int dfs(int u, int st, bool lead, bool op) {
if (u == 0) return 1; // 如果到头了,那么当前检查的数字是OK的
if (!op && !lead && ~f[u][st]) return f[u][st]; // 不贴上界,非前导零,计算过
int ans = 0, up = op ? a[u] : 9;
for (int i = 0; i <= up; i++) {
if (abs(st - i) < 2) continue; // 相邻两个数字,差不能小于2
if (lead && i == 0) // 继续前导零
ans += dfs(u - 1, -2, true, op && i == a[u]);
else // 不再是前导零
ans += dfs(u - 1, i, false, op && i == a[u]);
}
// 不贴上界,非前导零,记录下来结果
if (!op && !lead) f[u][st] = ans;
return ans;
}
int calc(int x) {
al = 0;
while (x) a[++al] = x % 10, x /= 10;
return dfs(al, -2, 1, 1); // 注意st的初始化-2
}
signed main() {
int l, r;
cin >> l >> r;
// windy数是数字本身的一种性质,可以将memset放在外层
memset(f, -1, sizeof f);
cout << calc(r) - calc(l - 1) << endl;
return 0;
}
```