You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

AcWing 1083. Windy

一、题目描述

Windy 定义了一种 Windy 数:不含前导零相邻两个数字之差至少为 2 的正整数被称为 Windy 数。

Windy 想知道,在 AB 之间,包括 AB,总共有多少个 Windy 数?

输入格式 共一行,包含两个整数 AB

输出格式 输出一个整数,表示答案。

数据范围 1≤A≤B≤2×10^9

输入样例1

1 10

输出样例1

9

输入样例2

25 50

输出样例2

20

二、解题思路

  • 使用带前导零参数的模板
  • 相邻两个数字:这需要传递前一位数字,以方便进行比较,用st代表。
  • 差至少为2,可以用abs(st-i)>2进行判断
  • 起始值如何合理?就是传递st=-2,这样,当前位就算是0,也就满足条件的,可以正常开始运行的逻辑。

三、实现代码

#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;
}