← 返回题目页

A1134 [CSP-S 2023] 密码锁

标程

#include <bits/stdc++.h>
using namespace std;

// CSP-S 2023 密码锁(A1134)
// 思路:枚举全部 10^5 个正确密码,用「差值模式」判断能否由锁车状态反推得到。
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;
    vector<array<int, 5>> st(n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < 5; j++) {
            cin >> st[i][j];
        }
    }

    int ans = 0;
    // p 看成五位十进制数(允许前导零),于是 0 ~ 99999 恰好覆盖全部密码。
    for (int p = 0; p < 100000; p++) {
        array<int, 5> pw{};
        int x = p;
        for (int j = 4; j >= 0; j--) {
            pw[j] = x % 10;
            x /= 10;
        }

        bool ok = true;
        for (int i = 0; i < n && ok; i++) {
            int d[5] = {0, 0, 0, 0, 0};
            int cnt = 0, first = -1, second = -1;
            for (int j = 0; j < 5; j++) {
                d[j] = (st[i][j] - pw[j] + 10) % 10;
                if (d[j] != 0) {
                    cnt++;
                    if (first == -1) first = j;
                    else if (second == -1) second = j;
                }
            }
            // 情况一:只有 1 个拨圈不同 —— 转动一个拨圈就能得到这个状态。
            if (cnt == 1) continue;
            // 情况二:2 个相邻拨圈不同且转动幅度相同 —— 同时转动两个相邻拨圈。
            if (cnt == 2 && second == first + 1 && d[first] == d[second]) continue;
            ok = false;
        }
        if (ok) ans++;
    }

    cout << ans << "\n";
    return 0;
}

动画演示