1 条题解

  • 0
    @ 2026-4-1 12:48:07

    题目理解

    给定一个正整数 xx,要求找到一个正整数 yy,使得:

    1. (x & y)>0(x \ \& \ y) > 0(即 xxyy 在二进制下至少有一位同时为 11
    2. (x  y)>0(x \ \oplus \ y) > 0(即 xxyy 在二进制下至少有一位不同)

    要求输出任意一个满足条件的 yy


    提示解析

    题目提示将 xx 分为两种情况:

    • x=2kx = 2^k(即 xx22 的幂次)
    • x2kx \neq 2^k

    解题思路

    pip_i 表示 xx 的第 ii 位(从 00 开始),qiq_i 表示 yy 的第 ii 位。

    条件翻译:

    • (x & y)>0    i,pi=qi=1(x \ \& \ y) > 0 \iff \exists i, p_i = q_i = 1
    • (x  y)>0    i,piqi(x \ \oplus \ y) > 0 \iff \exists i, p_i \neq q_i

    情况一:x2kx \neq 2^k

    此时 xx 的二进制表示中至少有两个 11

    1. 找到最低位 kk 使得 pk=1p_k = 1(即 xx 的最低位 11 的位置)
    2. qk=1q_k = 1,这样满足了第一个条件((x & y)>0(x \ \& \ y) > 0
    3. 由于 xx 还有另外的 11,而 yy 只有这一位是 11,所以 xyx \neq y,因此 (x  y)>0(x \ \oplus \ y) > 0 自动成立

    所以此时 y=2ky = 2^k 就是一个解。


    情况二:x=2kx = 2^k

    此时 xx 的二进制表示中只有一个 11

    1. 先令 qk=1q_k = 1,这样满足了第一个条件
    2. 但如果 yy 只有这一位是 11,那么 y=xy = x,此时 x  y=0x \ \oplus \ y = 0,不满足第二个条件
    3. 因此需要再找一个最低位 jj 使得 pj=0p_j = 0(即 xx 在该位为 00),令 qj=1q_j = 1
    4. 此时 yy 有两位为 11(x & y)=2k>0(x \ \& \ y) = 2^k > 0(x  y)=2j>0(x \ \oplus \ y) = 2^j > 0,满足条件

    所以此时 y=2k+2jy = 2^k + 2^j 是一个解。


    算法实现

    标程使用了 lowbit 函数(x & -x)来找到最低位的 11

    int w = lowbit(x);  // w = 2^k,其中 k 是最低位 1 的位置
    while (!(w ^ x) || !(w & x)) w++;
    

    解释:

    • 初始 w=2kw = 2^k
    • 如果 wx=0w \oplus x = 0,即 w=xw = x,说明 xx22 的幂,需要进入情况二
    • 否则,直接输出 ww 即可(情况一)
    • 循环中的条件 !(w & x) 实际上永远不会成立(因为 ww 始终是 xx 的某个位),这个写法可能是为了处理边界情况

    更简洁的实现:

    int lowbit = x & -x;
    if (x != lowbit) {
        cout << lowbit << endl;
    } else {
        // x 是 2 的幂,找一个最低的 0 位
        int ans = lowbit;
        for (int j = 0; j < 31; j++) {
            if (!((x >> j) & 1)) {
                ans += (1 << j);
                break;
            }
        }
        cout << ans << endl;
    }
    

    时间复杂度

    O(1)O(1) 每次查询,因为只需检查固定的位数(32326464 位)。


    完整代码(带注释)

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        int T;
        cin >> T;
        while (T--) {
            int x;
            cin >> x;
            
            // lowbit = x 的最低位的 1 所表示的值
            int lowbit = x & -x;
            
            if (x != lowbit) {
                // 情况一:x 不是 2 的幂
                cout << lowbit << endl;
            } else {
                // 情况二:x 是 2 的幂
                // 找到最低的 0 位
                int ans = lowbit;
                for (int j = 0; j < 31; j++) {
                    if (!((x >> j) & 1)) {
                        ans += (1 << j);
                        break;
                    }
                }
                cout << ans << endl;
            }
        }
        return 0;
    }
    

    举例验证

    xx 二进制 输出 yy 验证
    33 1111 11 3&1=1>03 \& 1 = 1 > 0, 31=2>03 \oplus 1 = 2 > 0
    55 101101 5&1=1>05 \& 1 = 1 > 0, 51=4>05 \oplus 1 = 4 > 0
    44 100100 55 4&5=4>04 \& 5 = 4 > 0, 45=1>04 \oplus 5 = 1 > 0
    88 10001000 99 8&9=8>08 \& 9 = 8 > 0, 89=1>08 \oplus 9 = 1 > 0

    • 1

    信息

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