Skip to content

喵~ 各位小主人们好呀!咱是猫娘小助手,今天由咱来带大家解决这道 "Little Xor" 问题吧!这道题就像在成堆的猫抓板里找最舒服的那个一样,只要有耐心,就一定能找到的,嘿嘿~

题目大意

这道题是说,有一个叫 Petya 的小朋友,他有一个装着非负整数的数组。他想请我们帮忙,从这个数组里找出一个 连续的片段 (也就是子数组),让这个片段里所有数字的 异或 (XOR) 和最大。最后,我们只要告诉他这个最大的异或和是多少就可以啦,喵~

举个例子:如果数组是 [1, 2, 1, 1, 2],那么 12 组成的片段 [1, 2] 的异或和是 1 ^ 2 = 3。事实证明,3 就是这个数组能得到的最大异或和啦。

题解方法

看到题目给的数据范围 n <= 100,咱的猫耳朵立刻就竖起来了!这个数字也太小了吧!(ฅ'ω'ฅ)

这么小的数据量,意味着咱根本不需要想什么复杂又高级的算法,直接用最朴素、最暴力的方法就能轻松解决啦!

思路就是:枚举所有可能的连续子数组

怎么枚举呢?咱可以用两层循环来搞定:

  1. 第一层循环,咱用一个变量 i 来确定子数组的 起点i 可以从数组的第一个元素一直遍历到最后一个元素。
  2. 第二层循环,咱用另一个变量 j 来确定子数组的 终点。对于每一个固定的起点 ij 就从 i 开始,一直向后遍历到数组的末尾。

这样一来,以 i 为起点、j 为终点的所有连续子数组 [a[i], a[i+1], ..., a[j]] 就都被咱找到啦。

在第二层循环里,我们一边扩展子数组的终点 j,一边计算从 a[i]a[j] 的异或和。每次算出一个新的异或和,就和我们当前记录的 max_xor (最大异或和) 比较一下,如果新的更大,就更新 max_xor 的值。

当所有循环都结束后,max_xor 里存的就是最终的答案啦!是不是很简单喵~?

题解

下面就是这份思路对应的 C++ 代码啦,咱在里面加了一些注释,方便小主人们理解哦。

cpp
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>

int main() {
    // 为了让程序跑得快一点点,像小猫追毛线球一样快!
    std::ios_base::sync_with_stdio(false);
    std.cin.tie(NULL);

    // 先问问数组有多长,喵~
    int n;
    std::cin >> n;

    // 准备一个篮子 (vector) 来装数字
    std::vector<int> a(n);
    // 把数字一个个放进篮子里
    for (int& val : a) {
        std::cin >> val;
    }

    // 用一个变量来记录咱找到的最大的异或和
    // 一开始当然是 0 啦
    int max_xor = 0;

    // 第一层循环,固定子数组的起点 i
    for (int i = 0; i < n; ++i) {
        // 对于每个新的起点,咱都要重新开始计算异或和
        int current_xor = 0;
        // 第二层循环,从起点 i 开始,向后扩展子数组的终点 j
        for (int j = i; j < n; ++j) {
            // 把新遇到的数字 a[j] 异或到当前片段的和里
            current_xor ^= a[j];
            // 看看当前这个片段的异或和是不是比咱之前找到的都大
            max_xor = std::max(max_xor, current_xor);
        }
    }

    // 所有可能的片段都检查完啦,把最好的结果告诉 Petya 吧!
    std::cout << max_xor << std::endl;

    return 0;
}

知识点介绍:异或 (XOR)

最后,咱来聊聊这道题的核心——异或 (XOR) 运算,它在 C++ 和 Java 里用 ^ 这个符号表示。

异或是一种 位运算,意思是它是在数字的二进制表示上逐位进行的。

它的运算规则超级简单,可以用一句话概括:相同为 0,不同为 1

具体来说,对于二进制的每一位:

  • 0 ^ 0 = 0 (两位相同)
  • 0 ^ 1 = 1 (两位不同)
  • 1 ^ 0 = 1 (两位不同)
  • 1 ^ 1 = 0 (两位相同)

举个栗子:计算 5 ^ 3

  1. 先把 53 转换成二进制:

    • 5 的二进制是 101
    • 3 的二进制是 011 (为了对齐,咱在前面补个0)
  2. 然后逐位进行异或运算:

      1 0 1  (这是 5)
    ^ 0 1 1  (这是 3)
    ---------
      1 1 0  (这是结果)
    • 最高位:1 ^ 0 = 1
    • 中间位:0 ^ 1 = 1
    • 最低位:1 ^ 1 = 0
  3. 最后把结果 110 转换回十进制,就是 4 + 2 + 0 = 6。所以 5 ^ 3 = 6

异或还有一些很有趣的性质,就像猫咪的神秘习性一样,喵~

  • 归零律: 任何数和它自己异或,结果都是 0。 (a ^ a = 0)
  • 恒等律: 任何数和 0 异或,结果还是它自己。 (a ^ 0 = a)
  • 交换律: a ^ b = b ^ a
  • 结合律: (a ^ b) ^ c = a ^ (b ^ c)

这些性质在很多算法题里都有奇妙的用处哦!希望这次的讲解对小主人们有帮助,那么下次再见啦,喵~ (ฅ^•ﻌ•^ฅ)

Released under the MIT License.