仍待更新
1.资料来源
2.题目
异或线性基
设数组$p$表示序列{$a_n$}的线性基,待插入数为$a$,下标从0开始。
将$a$转化为二进制,从高位开始,若当前位为1,并且线性基$p$的第$i$位上没有数,那就赋成当前值$x$。否则将$x$异或 $p_i$
插入操作(贪心做法)
void insert(int a)
{
for(int i=M;i>=0;i--)
if(a&(1LL<<i))
{
if(p[i]) a=a^p[i];
else{p[i]=a; return ;}
}
}
高斯消元法求线性基,可直接得到$p_i$的最小值,常用于下面求第$k$小异或值(用$zero$布尔值判断是否存在异或值为0的情况)
插入(高斯消元)
void gauss()
{
int j=(1ll<<62),k=1,i;
for(;j;j>>=1)
{
for(i=k;i<=n;i++)
{
if(a[i]&j) break;
}
if(i>n) continue;
swap(a[i],a[k]);
for(i=1;i<=n;i++)
{
if(i!=k && a[i]&j) a[i]^=a[k];
}
k++;
}
k--;
if(k!=n) zero=true;
else zero=false;
n=k;
}
求异或最大值
纯贪心遍历线性基,逐个异或线性基{$p_i$}
int pmax()
{
int ans=0;
for(int i=M;i>=0;i--) ans=max(ans,ans^p[i]);
return ans;
}
求k小值
利用上述 高斯消元插入法 得到的线性基。
将$k$先转成二进制,假如第$i$位为$1$,则$ans$异或线性基中第$i$个元素(注意不是直接异或 $p_{i-1}$)。
int getk_th()
{
int ans=0;
int k; cin>>k;
if(zero) k--;
if(!k) return 0;
for(int i=n;i;i--)
{
if(k&1) ans^=a[i];
k>>=1;
}
if(k) return -1;
return ans;
}