专栏文章
题解:P14359 [CSP-J 2025] 异或和 / xor(民间数据)
P14359题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minfogfd
- 此快照首次捕获于
- 2025/12/02 01:39 3 个月前
- 此快照最后确认于
- 2025/12/02 01:39 3 个月前
P14359 [CSP-J 2025] 异或和 / xor 题解
题目分析
题目要求从序列中选出尽可能多的不相交区间,每个区间的异或和都等于给定的 。我们需要找出最多能选出多少个这样的区间。
解题思路
定义前缀异或和数组 ,且 ,那么区间 的异或和就是 。我们需要找到 ,即 。为了得到最多的不相交区间,我们应该尽可能选择结束位置靠左的区间,这样可以为后面的区间留出更多空间。
用 记录当前能选出的最多区间数,用 数组记录每个前缀异或值对应的最大 值,遍历序列,对于每个位置,计算当前前缀异或和 ,检查是否存在 ,如果存在则更新 ,更新 为当前 值。
代码实现
CPP#include <bits/stdc++.h>
using namespace std;
const int MAX = 1 << 20;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n, k;
cin >> n >> k;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
vector<int> max_dp(MAX, -1);
max_dp[0] = 0; // 前缀异或和为 0 时,dp 值为 0
int s = 0; // 前缀异或和
int dp = 0; // 当前能选出的最多区间数
for (int i = 1; i <= n; i++) {
s ^= a[i];
int x = s ^ k;
// 如果 x 存在且可以形成新区间
if (x < MAX && max_dp[x] != -1) {
dp = max(dp, max_dp[x] + 1);
}
// 更新当前前缀异或值对应的最大 dp 值
if (max_dp[s] == -1 || dp > max_dp[s]) {
max_dp[s] = dp;
}
}
cout << dp << endl;
return 0;
}
正确性证明
关键概念
- 定义前缀异或和数组 ,其中 ,且 。
- 区间 的异或和为 。因此,要求 ,即 。
算法思路
- :表示当前处理到位置 时能选出的最多区间数。
- 数组: 记录当遇到前缀异或和为 时,能选出的最多区间数。
遍历序列时,对于每个位置 :
- 计算当前前缀异或和 。
- 计算 。如果 存在(不为 ),则说明存在某个位置 ()满足 ,从而区间 的异或和为 。此时,可以形成一个新的区间,更新 。
- 更新 ,确保 记录当前最优值。
数学归纳法证明
定义:设 表示考虑前 个元素时能选出的最大区间数。
归纳基础:
- 当 时,,,表示没有选择任何区间,。
归纳步骤:
假设对于所有 , 已正确计算。考虑 :
- 可能等于 ,即不选择以 结尾的区间。
- 或者,如果存在 满足 ,则区间 的异或和为 ,此时 。
因此,有:
由于遍历顺序从 到 , 数组始终记录当前位置之前的最优值,因此算法能正确计算 。
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...