1 条题解

  • 0
    @ 2026-5-4 17:12:11

    题意简述

    给定长度为 n1n-1 的数组 bb,需要构造长度为 nn 的数组 aa,使得

    $$a_i \mathbin{\&} a_{i+1} = b_i \quad (1 \le i \le n-1) $$

    若不存在,输出 -1

    逐位分析

    按位与的性质:某一位为 11 当且仅当参与运算的两个数在该位都为 11
    因此,若 bib_i 的第 kk 位为 11,则 aia_iai+1a_{i+1} 的第 kk必须都是 11
    bib_i 的第 kk 位为 00,则 aia_iai+1a_{i+1} 的第 kk不能同时为 11

    构造方法

    1. 初始化 a1ana_1 \dots a_n00
    2. 遍历 i=1n1i = 1 \dots n-1,将 aia_iai+1a_{i+1} 都按位或上 bib_i。这一步将所有必须为 11 的位设置好。
    3. 再次遍历 i=1n1i = 1 \dots n-1,检查 (ai&ai+1)(a_i \mathbin{\&} a_{i+1}) 是否等于 bib_i
      • 若相等,说明所有 00 位的限制也满足(因为那些位上不会同时为 11)。
      • 若不等,说明某个必须为 00 的位被迫变成了 11,此时无解,输出 -1

    正确性说明

    • 步骤 2 设置了最少的必要 11 位,如果这样仍然导致某个 bi=0b_i=0 的位在 aia_iai+1a_{i+1} 上同时为 11,那么任何其他赋值也不可能满足(因为那些 11 位是强制要求的)。
    • 若检查通过,则构造出的 aa 就是合法的。

    时间复杂度 O(n)O(n)(每一位独立操作可以合并为按位或),总复杂度 O(n)105O(\sum n) \le 10^5,足够快。

    参考代码

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
        int t;
        cin >> t;
        while (t--) {
            int n;
            cin >> n;
            vector<int> b(n - 1);
            for (int i = 0; i < n - 1; ++i) {
                cin >> b[i];
            }
    
            vector<int> a(n, 0);
            for (int i = 0; i < n - 1; ++i) {
                a[i] |= b[i];
                a[i + 1] |= b[i];
            }
    
            bool ok = true;
            for (int i = 0; i < n - 1; ++i) {
                if ((a[i] & a[i + 1]) != b[i]) {
                    ok = false;
                    break;
                }
            }
    
            if (!ok) {
                cout << "-1\n";
            } else {
                for (int i = 0; i < n; ++i) {
                    cout << a[i] << " \n"[i == n - 1];
                }
            }
        }
        return 0;
    }
    
    • 1

    信息

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