1. 程式人生 > 其它 >CF 1567B MEXor Mixup

CF 1567B MEXor Mixup

題意概述:對於一個非負整數序列,給出不屬於該整數序列的最小非負整數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;
}