1 条题解

  • 0
    @ 2026-5-19 19:46:34

    C. Combination Lock 详细题解

    一、问题重述

    构造一个长度为 nn 的排列 p1,p2,,pnp_1, p_2, \dots, p_n(数字 11nn 各出现一次),使得对于每一个循环移位,恰好有一个位置 ii 满足该位置上的值等于其位置编号。

    输出任意一个满足条件的排列;如果不存在,输出 1-1


    二、核心推导

    2.1 数学转化

    将排列下标从 00 开始考虑(0in10 \le i \le n-1),设 pip_i 为下标 ii 处的值(1pin1 \le p_i \le n)。

    一个循环移位相当于将数组向右移动 kk 位(k=0,1,,n1k = 0, 1, \dots, n-1)。原下标 ii 在移位后的新下标为 (i+k)modn(i + k) \bmod n

    “恰好有一个固定点”意味着:对于每个 kk,存在唯一的 ii 使得:

    (i+k)modn=pi1(值域从 0 开始)(i + k) \bmod n = p_i - 1 \quad \text{(值域从 0 开始)}

    qi=pi1[0,n1]q_i = p_i - 1 \in [0, n-1],则条件为:

    (i+k)modn=qi(i + k) \bmod n = q_i

    整理得:

    kqii(modn)k \equiv q_i - i \pmod{n}

    对于固定的 kk,由 ii 唯一确定。因此映射 kik \mapsto i 是双射。故 {qiimodni=0,,n1}\{q_i - i \bmod n \mid i = 0,\dots,n-1\} 必须恰好是 {0,1,,n1}\{0,1,\dots,n-1\}

    2.2 必要条件

    对全体 ii 求和:

    $$\sum_{i=0}^{n-1} (q_i - i) \equiv \sum_{k=0}^{n-1} k \pmod{n} $$

    左边:

    $$\sum q_i - \sum i = \frac{n(n-1)}{2} - \frac{n(n-1)}{2} = 0 $$

    右边:

    k=0n1k=n(n1)2\sum_{k=0}^{n-1} k = \frac{n(n-1)}{2}

    因此:

    n(n1)20(modn)\frac{n(n-1)}{2} \equiv 0 \pmod{n}

    nn120(modn)n \cdot \frac{n-1}{2} \equiv 0 \pmod{n},等价于 n12\frac{n-1}{2} 为整数?不对,检查:

    n(n1)2modn=0\frac{n(n-1)}{2} \bmod n = 0 当且仅当 nn 是奇数。因为 n(n1)/2=n(n1)/2n(n-1)/2 = n \cdot (n-1)/2nn 整除该项当且仅当 (n1)/2(n-1)/2 是整数,即 nn 为奇数。

    结论:当 nn 为偶数时无解,输出 1-1


    三、构造方案(nn 为奇数)

    nn 为奇数时,一个简单的构造是:

    p=[n,n1,n2,,2,1]p = [n, n-1, n-2, \dots, 2, 1]

    即降序排列。

    验证:将 pp 转换为 00-基 qi=(ni)modnq_i = (n - i) \bmod n?实际 pi=nip_i = n - iii11 开始),qi=ni1q_i = n - i - 1。计算 qiiq_i - i

    qii=(ni1)i=n2i1(modn)q_i - i = (n - i - 1) - i = n - 2i - 1 \pmod{n}

    ii0,1,,n10,1,\dots,n-1 时,n2i1modnn - 2i - 1 \bmod n 遍历所有 nn 个不同值(因为 nn 奇数,22 可逆)。因此每个 kk 恰好对应一个 ii


    四、标程代码

    #include <iostream>
    using namespace std;
    
    void solve() {
        int n;
        cin >> n;
        if (n % 2 == 0) {
            cout << -1 << endl;
            return;
        }
        for (int i = n; i > 0; i--) {
            cout << i << " \n"[i == 1];
        }
    }
    
    int main() {
        int t;
        cin >> t;
        while (t--) {
            solve();
        }
        return 0;
    }
    

    五、示例验证

    示例 1:n=4n = 4(偶数)

    输出 -1

    示例 2:n=5n = 5

    输出 5 4 3 2 1,检查各循环移位(00‑基):

    • 移位 0:4 3 2 1 0 → 固定点:下标 4(值 0)? 等,需要仔细。 实际上原例输出是 4 1 3 5 2,说明不唯一。本题只要任意解,降序也可行。

    示例 3:n=3n = 3

    输出 3 2 1,循环移位:

    • 3 2 1:固定点?值=位置?3 在位置 1 不等,2 在位置 2 等,1 在位置 3 不等 → 1 个固定点
    • 1 3 21=位置1,3≠2,2=位置3?位置3 值是2 → 1 个固定点
    • 2 1 32≠1,1≠2,3=3 → 1 个固定点 ✅

    六、复杂度分析

    • 每个测试用例 O(n)O(n)
    • nn 不超过 2×1052 \times 10^5t500t \le 500,可通过

    七、总结

    条件 结论
    nn 为偶数 无解,输出 1-1
    nn 为奇数 有解,降序排列 [n,n1,,1][n, n-1, \dots, 1] 是一种构造

    核心思想:利用模 nn 的线性同余性质,推导出 nn 必须为奇数,并给出简单构造。

    • 1

    信息

    ID
    7261
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者