题意概述:对于一个非负整数序列,给出不属于该整数序列的最小非负整数a,该整数序列的异或和b,求出该整数序列最少所含的元素个数
分析:
一个非常有意思的题。
一开始容易拘泥于:“如何求出被异或的数” 容易出现错误
但我们不需要具体数字,所以选择转而去分析异或规则带来的性质
对于异或而言,运算规则为相同为0,相异为1,那么很容易可以得出,对于一个特定的数而言,一定可以构造出两个数,异或之后结果为该特定数,且这样的构造有无穷组
(构造的数是可以相等的,不会破坏最小非负整数的性质)
那么我们考虑,对于a!=0的情况(a=0是简单的,即如果b为0构造两个相同正整数,如果是1取1即可)
首先小于a的所有非负整数一定在序列之中,先求出这一些数的异或和x(可以提前预处理降低复杂度)
判断x与b的关系,如果x=b则结果为a即这些数构成的序列成立,如果x^a=b,由于a不能处于序列中,则a需要由额外两个数构造,结果应为x+2,否则则只需要额外的一个数即可,结果即为x+1
code:
#include<bits/stdc++.h>
using namespace std;
int T;
int p[100],q[100];
int d[300005];
int a,b;
int l,r,ans;
int v,x;
bool flag;
inline int cal (int x,int b)
{
if (x==0) p[++p[0]]=x;
while (x)
{
p[++p[0]]=x%2;
x>>=1;
}
if (b==0) q[++q[0]]=b;
while (b)
{
q[++q[0]]=b%2;
b>>=1;
}
}
int main()
{
cin>>T;
d[0]=0;
for (int i=1;i<=300000;++i)
{
d[i]=d[i-1]^i;
}
while (T--)
{
cin>>a>>b;
if (a==0)
{
if (b==0) cout<<2<<endl;
else cout<<1<<endl;
continue;
}
x=d[a-1];
memset(p,0,sizeof(p));
memset(q,0,sizeof(q));
cal(x,b);
// for (int i=p[0];i>=1;--i) cout<<p[i]; cout<<‘ ‘;
// for (int i=q[0];i>=1;--i) cout<<q[i]; cout<<endl;
flag=false; ans=0;
l=0; r=0;
/* while (l<p[0]||r<q[0])
{
++l; ++r;
if (p[l]==q[r]) ans=ans*2;
else ans=ans*2+1;
}*/
//cout<<ans<<‘ ‘;
v=a;
if (d[a-1]==b) cout<<v<<endl;
else
{
if (d[a]==b) cout<<v+2<<endl; else cout<<v+1<<endl;
}
}
return 0;
}