思路:
,则有,也就是说只要知道A1就可以求任意A。由于A是升序排列,所以对于任意,二进制所包含1的最高位第k位来说,表明与第k位相反,要大一些,所以它的第k位为1,的第k位为0,例如Bi=10对应的二进制数为1010,最高位1就是第3位,所以就能确定Ai+1的第三位为1,Ai的第三位为0;类似这样操作,就能找出A中很多确定的值,不确定的位根据k去判断。为了方便计算,我们的是要去预处理b的前缀异或,然后解出a1就能得出,为了找到a1的某些确定值,我们同样的去找bi最高位1为第k位,然后记录s[i]的第k位的值,因为要使a[i+1]的第k位为1,由于,那么只要记录下si,就能根据a1的值得到ai+1的第k位为1;而且若出现多次相同的最高位1,前缀异或值必须相等,否则矛盾输出-1。
对于未知位,可以把这些未知位紧贴看成一个二进制数,使此二进制的值为k-1,就是所求字典序第k小的值。例如k=3,a1=1x1x0,x代表未知,将两个未知位紧贴xx,让它的值为2也就是二进制表示10,就是字典序第三小的值,所以a1=11100。
#include<bits/stdc++.h>
using namespace std;
int s[1000005];
int a[1000005];//第i位上是否为1
int a1[1000005];//第i位上为1的前i-1位异或和
int main()
{
int T;
cin>>T;
int h=0;//最高位
while(T--)
{
int n,k;
cin>>n>>k;
memset(a,0,sizeof(a));
memset(a1,0,sizeof(a1));
int flag=1;
int a2=30;//所包含的最高位,不能超过30
for(int i=1;i<n;i++)
{
int b;
cin>>b;
s[i+1]=s[i]^b;
if(b==0)continue;
h=0;
while(b)
{
h++;
b/=2;
}
h-=1;
//相同最高位1的前缀异或值相同
if(a[h]&&((s[i]>>h)&1)!=a1[h]) flag=0;
if(!a[h])a2-=1;
a[h]=1;
a1[h]=(s[i]>>h)&1;
}
if(flag==0||(1<<a2)<k)cout<<-1<<endl;
else
{
int a11=0;
k-=1;
int cnt=0;
//确定a1
for(int i=0;i<30;i++)
{
//根据最高位1的前缀异或,确定a1的对应位的值。
if(a[i])a11|=(a1[i]<<i);
else
{
int m=((k>>cnt)&i)<<i;//未知位,根据k的二进制数分配
a11|=m;
cnt++;
}
}
for(int i=1;i<=n;i++)
{
cout<<int(a11^s[i])<<" ";
}
cout<<endl;
}
}
}