CF1567B - MEXor Mixup
MEXor Mixup(源地址自⇔CF742B)
Problem
Alice gave Bob two integers \(a\) and \(b\) ( \(a>0\) and \(b≥0\) ). Being a curious boy, Bob wrote down an array of non-negative integers with \(MEX\) value of all elements equal to \(a\) and \(XOR\) value of all elements equal to \(b\) .
What is the shortest possible length of the array Bob wrote?
Recall that the \(MEX\) (Minimum EXcluded) of an array is the minimum non-negative integer that does not belong to the array and the \(XOR\) of an array is the bitwise \(XOR\) of all the elements of the array.
Input
The input consists of multiple test cases. The first line contains an integer \(t\) ( \(1≤t≤5*10^4\) ) — the number of test cases. The description of the test cases follows.
The only line of each test case contains two integers \(a\) and \(b\) (\(1≤a≤3*10^5\) ; \(0≤b≤3*10^5\) ) — the \(MEX\) and \(XOR\) of the array, respectively.
Output
For each test case, output one (positive) integer — the length of the shortest array with \(MEX\) \(a\) and \(XOR\) \(b\) . We can show that such an array always exists.
Example
5
1 1
2 1
2 0
1 10000
2 10000
3
2
3
2
3
Note
In the first test case, one of the shortest arrays with \(MEX\) \(1\) and \(XOR\) \(1\) is
[0,2020,2021]
.
In the second test case, one of the shortest arrays with \(MEX\ 2\) and \(XOR\ 1\) is[0,1]
.
It can be shown that these arrays are the shortest arrays possible.
tag:
⇔位运算、⇔数论(规律题)
题意:
对于给定的 \(a\) 、 \(b\) ,要求找到一个最短的数组,满足:
1 . 数组内的全部元素必须 \(\geq 0\) 。
2 . \(a\) 是不包含在这个数组里的最小正整数。
3 . 数组中所有元素按位异或和恰好等于 \(b\) 。
输出最短数组的长度。
思路:
由条件1和2可知:数组内必定存在 \(a\) 个数,为 [0,1,2,……,a-1]
。
由条件3可知:
在没有限制的条件下,对于手中的任意一串二进制数据 \(b1\) ,要得到指定的二进制数据 \(b2\) ,仅有两种情况可以讨论:
【情形1】\(b1==b2\) ,此时,不用进行任何操作。
【情形2】\(b1!=b2\) ,此时,容易证明,一定能找到唯一的一串二进制数据 \(K\) ,使得 \(K\bigoplus b1\) 为 \(b2\) 。
而本题的限制条件在于 \(K\) 不能等于 \(a\) 。
【情形3】若出现等于的情况,则需要另外寻找两个数字 \(b3\) 与 \(K\) ,使得 \(b3\bigoplus b1\) 得到新的 \(b1'\) ,再通过\(K\bigoplus b1'\) 得到所求数据 \(b2\) (例如样例数据1)。
所以,综上,需要先计算出 \(0\) 至 \(a-1\) \((a=0,1,2,…,3*10^5)\) 所有数字的异或和 \(XOR_{a-1}\) 。此后,对于每一组读入的 \(a\ b\) 进行判断。
1 . 若 \(XOR_{a-1}==b\) ,即为上方讨论到的【情形1】,直接输出 \(a\) 。
2 . 若 \(a\bigoplus XOR_{a-1}==b\) ,即为上方讨论到的【情形3】,则答案为 \(a+2\) 。
3 . 其余情况即为上方讨论到的【情形2】,答案均为 \(a+1\) 。
AC代码:
//A WIDA Project
#include<bits/stdc++.h>
using namespace std;
int a,b,a1,b1,T,numa,numb,M[300030];
void Prepare(){//计算按位异或和
bitset<100>B1;bitset<100>B2;
B2=0;
for(int i=0;i<300005;i++){
B1=i;
B2=B1^B2;
M[i]=B2.to_ullong();
}
}
int main(){
ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>T;
for(int t=1;t<=T;t++){
cin>>a>>b;
if(M[a-1]==b) cout<<a<<"\n";
else if(M[a]==b) cout<<a+2<<"\n";
else cout<<a+1<<"\n";
}
return 0;
}
一些优化:
对于本题求解过程中需要进行计算的“ \(0\) 至 \(a-1\) \((a=0,1,2,…,3*10^5)\) 所有数字的异或和 \(XOR_{a-1}\) ”,我在打这场比赛的时候直接采用了 \(STL\) 容器中的 \(bitset\) 容器,其处理效率已经非常优秀了,但我的队友在赛后查阅资料寻找到了一种更为优秀的求解方法,其时间复杂度到达了夸张的 \(O(1)\) ,故特此一并附于下方,供大家参考学习。
unsigned xor_n(unsigned n){//计算0~n间所有数字的按位异或和
unsigned t=n&3;
if(t&1) return t/2u^1;
return t/2u^n;
}
错误次数:4次
原因:误以为所给定的 \(b\) 为二进制数,多进行了一次进制转换。
文 / WIDA
2021.09.06成文
2021.09.09最后一次修改
首发于WIDA个人博客,仅供学习讨论
更新日记:
2021.09.09 优化了部分语句,增加了优化的内容