题目描述
输入描述
输出描述
输入样例
5
1 1
2 1
2 0
1 10000
2 10000
输出样例
3
2
3
2
3
提示
题目大意: 给定两个数 a 、b,分别表示数组的 Mex 函数值( Mex函数运算:求数组内未出现的最小非负整数,如数组 Mex { 0,1,2,3,5 } = 4 )及数组内所有元素的异或值,求能够满足该条件的数组的最小长度。
万恶的 学校 acm 队今日也开始启用每日一题了,没有办法,那就开始把 cf 冲了吧()
本题中的 Mex 函数及异或和问题为 SG 函数的前置知识,虽然本题并没有什么太大联系 。解出本题前先要了解到异或运算和其他基础运算的相似性,即对于 a ^ b = x ,当已知 a 和 x 时,b 的存在性是唯一的,类比于 3 + ? = 7,此时的 ?只可为 4 。而若仅确定了异或的结果时,可进行多种组合,类比于 ?+ ?=7,可取 1 + 6 或 2 + 5 。
而对于 Mex 函数,当我们得到 a 的值时,则说明该数组中已经出现了 0 ~ n - 1 之间的所有元素,例 a = 4 时,该数组中必存在 { 0,1,2,3 },因此可考虑对 0 ~ n - 1 求异或和进行分类讨论:
①当该异或和恰好等于 b 时,说明最小符合条件的数组长度即为 a,不需要再从 a 之后取其他元素进行凑值,直接输出 a 即可。
②当该异或和恰好需要异或上 a 才能等于 b 时,由于此时的 a 不可直接取(否则将改变 Mex 函数的值),因此需要从 a 之后取两个元素进行异或,使得它们异或后的值恰好等于 a 以替代不可直接选取的 a,因此数组的最小长度为 a + 2 。
③当该异或和异或上 a 不等于 b 时,此时根据唯一性在 a 之后的元素中挑选出符合条件的值即可,数组的最小长度为 a + 1 。
需要注意的是,本题需要预处理前缀异或和,否则在 text 2 就 T 了 ( 血的教训 ) 。
参考代码
#include <bits/stdc++.h>
using namespace std;
int e[300005];
int main(){
int t,a,b;
cin>>t;
for(int i=1;i<=300000;i++)
e[i]=e[i - 1]^i;
while(t--){
cin>>a>>b;
int sum=e[a-1];
if(sum==b)
cout<<a<<endl;
else if((sum^a)==b)
cout<<a+2<<endl;
else if((sum^a)!=b)
cout<<a+1<<endl;
}
return 0;
}