找回密码
 立即注册
查看: 14|回复: 0

2023年GESP五级烹饪问题解题指南:位运算优化AND**值求解

[复制链接]
  • 打卡等级:常驻代表
  • 打卡总天数:33
  • 打卡月天数:2
  • 打卡总奖励:223
  • 最近打卡:2025-08-14 15:12:36

39

主题

1

回帖

4597

积分

VIP会员

积分
4597
发表于 2025-7-21 10:53:08 | 显示全部楼层 |阅读模式
一、题目解读
2023年GESP五级编程竞赛中的“烹饪问题”(对应洛谷B3930)要求从给定的整数数组中寻找一个元素,使其与数组中其他任意元素的按位与(AND)结果**。题目需在保证结果尽可能大的同时,确保该元素本身存在于原数组中。这一问题的关键在于高效遍历与筛选符合条件的元素,避免暴力枚举带来的超时风险。
二、解题思路
采用位运算优化策略,核心思想是从高位到低位逐位构建目标元素,而非直接遍历数组元素。通过预设位掩码(mask)和临时结果(temp),每次尝试将当前位(从第30位开始)加入目标元素,并统计数组中满足“与操作后等于temp”的数值个数。若存在至少两个元素符合,则保留该位;否则撤销,确保最终结果既满足条件又是**可能的AND值。
三、解题步骤
1. 初始化:设置位掩码mask=0,初始**值max_and=0,从**位(第30位)开始检查。
2. 逐位尝试:
    将当前位i加入mask(mask |= (1 << i))。
    构建临时目标值temp(max_and | (1 << i))。
    遍历数组,统计满足(num & mask) == temp的元素个数count。
    若count≥2,则保留该位(更新max_and = temp);否则撤销该位(mask ^= (1 << i))。
3. 返回结果:最终max_and即为符合条件且**的AND值。
四、代码与注释
  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;

  4. // 寻找数组中元素的**AND值
  5. int findMaxAnd(vector<int>& nums) {
  6.     int mask = 0;          // 位掩码,用于构建目标值
  7.     int max_and = 0;       // 当前**AND值

  8.     // 从**位开始检查(30位对应int类型**二进制位)
  9.     for (int i = 30; i >= 0; i--) {
  10.         // 尝试设置这一位
  11.         mask |= (1 << i);          // 将第i位设为1
  12.         int count = 0;
  13.         int temp = max_and | (1 << i); // 临时目标值(当前位加入max_and)

  14.         // 统计有多少数字包含当前构建的模式
  15.         for (int num : nums) {
  16.             if ((num & mask) == temp) { // 若num与mask的与结果等于temp
  17.                 count++;
  18.                 if (count >= 2) break; // 若找到≥2个,无需继续遍历
  19.             }
  20.         }

  21.         // 如果有至少两个数字满足,保留这一位
  22.         if (count >= 2) {
  23.             max_and = temp;
  24.         } else {
  25.             mask ^= (1 << i); // 撤销这一位(异或操作清除第i位)
  26.         }
  27.     }

  28.     return max_and;
  29. }

  30. int main() {
  31.     int N;
  32.     cin >> N;          // 输入数组长度
  33.     vector<int> a(N);
  34.     for (int i = 0; i < N; i++) {
  35.         cin >> a[i];    // 读入数组元素
  36.     }

  37.     cout << findMaxAnd(a) << endl; // 输出结果
  38.     return 0;
  39. }
复制代码


五、总结
本解法巧妙利用位运算特性,将“寻找**AND值”转化为逐位决策问题,通过动态构建位掩码实现高效筛选。相比暴力枚举所有元素组合,该算法通过“提前终止无效位检查”和“计数满足条件元素”两大优化,大幅降低时间复杂度。这一思路对处理位操作相关的优化问题具有重要参考价值,尤其在编程竞赛中可显著提升解题效率。
来源:GESP题解

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表