异或线性基小记

其实是 F2n 空间的一个线性无关向量组。

前置知识

向量

定义 n 维向量 v=(v1,v2,vn) 为一个 n 元有序数组,记作 vRn,也即 n 维实数空间的一个向量。

定义如下运算:

  1. cR,vRn,cv=(cv1,cv2cvn),也就是每一维相乘,称为数乘。
  2. v1,v2Rn,v1+v2=(v1,1+v2,1,v1,2+v2,2v1,n+v2,n)

线性组合与张成空间

定义向量集 V={v1,v2,,vn},若存在 c1,c2cnR,满足向量 x=civi,则称 xVc1,c2cn 为权的线性组合,所有这样的 x 组成的集合称为 V 的张成空间,记作 span(V)

线性相关

对于向量集 V={v1,v2,,vn},若 j,vj 可以表达为 v1,v2vj1 的线性组合(注意取到 j1 即可)

定义:若向量集 B 线性无关,则称 B=span(B) 的一组基。

  • B 的任意真子集不是 span(B) 的基
  • 对于任意 vspan(B),存在唯一的 c1,c2cn,满足 vBc1,c2cn 为权的线性组合
  • 对于任意线性有关集 V,存在其真子集 B 满足 span(B)=span(V)

一个线性空间可能有多组基。

异或线性基

其实是 F2n 空间的一个 k 维子空间的基(指数域是 2n 维空间,算术意义上就是 [0,2n1] 的整数)

本质:

异或是 mod2 意义下的加法

将一个 [0,2n1] 的整数的每一二进制位看作取值为 0/1 的向量 vi,那么整数就对应上了一个向量。

类似地,我们定义张成空间:

  • 定义序列 a 的张成空间 span(a) 为从 a 中挑选若干数字可以异或得到的数字之和,换句话说就是 a 的所有子序列(可以空)元素异或和组成的集合

线性基的构造方法

构造线性基,我们考虑用增量法来构造线性基。假如现在要插入一个向量,从左向右不断消去1,直到出现了第一个无法消去的1,说明这个向量无法用现在的几组基底表示出来,所以将其插入线性基。

代码实现

ll d[65];
void ins(ll x){
    for(int i=60;i>=0;i--)
    if((x>>i)&1){
        if(d[i])x^=d[i];
        else{
            d[i]=x;break;
        }
    }
}

性质:

  1. 序列 a 的线性基为 span(a) 的一组基。
  2. 线性基是线性无关向量组
  3. 线性基里有值的元素个数所有张成空间是 span(a) 的向量组里最少的。
  4. B 为线性基,则 |span(a)|=2|B|

标准基,也称上三角基

一个张成空间很可能不止一组基,而标准基寻求一种标准的表示方法。

我们将一般的线性基执行如下操作:

for(int i=60;~i;--i)if(d[i])for(int j=i-1;~j;--j)if((d[i]>>j)&1)d[i]^=d[j];

容易发现操作后的线性基同样也是原张成空间的基,且满足将该向量组写为 01 矩阵后,每一行的最高位 1 满足该列仅有这个位置是 1

类似于阶梯型矩阵和简化阶梯型矩阵。

这相当有用。

应用

k 小异或和

k 从零开始。

线性基化为标准基,设其按大小排序后是 d0,d1,,dm,则该异或和为将 k 二进制分解后为 1 的位对应的 d 异或后的值。

读者自证不难

特别的,最大异或和就是全部异或起来,而 minxspan(B)xv 就是将 v 尝试插入线性基后剩下来的值。

线性基合并

直接暴力把一个线性基插入另一个线性基即可。

线性基求交

定义线性空间 Vi 的基底为 Bi,现在我们希望求出 V1V2 的基底 W

  • 引理:令 T=V1B2,若 B1(B2/T) 线性无关,则 T 是所求的 W 之一。

    证明:考虑反面证明,若 T 非法则线性有关,设 vV1V2 且不能被 T 表出。

    那么有 v=xy,xT,yB2/T,且 y>0

    因为 xTxV1,同时 vV1,所以 xv=yV1

    y 就可以被 B1 表出

    B1(B2/T) 线性相关。

考虑如何求出 W,可以考虑枚举 x:1|B2|

  • bxB2

    1. bx 可以被 B1{b1,b2bx1} 表出

      bx=pq,pV1,q{b1,b2bx1} 表出,则将 q 加入 W

    2. 否则不做任何操作。

证明这样可以求出 W,只需要证明 VB2WV1={0} 即可。

xVB2/WV1,x>0

则有 x 可以被 B1 以及 B2/W 表出,那么取出 B2/W 里下标最大的 bk,则有 bk 可以被 B2/W/{bk}B1 表出,那么与假设不符。

证毕。

struct node{
    int d[32];
    node(){
        memset(d,0,sizeof d);
    }
    void ins(int x){
        for(int i=31;i>=0;--i)if((x>>i)&1){
            if(d[i])x^=d[i];
            else {d[i]=x;return ;}
        }
    }
    bool count(int x){
        for(int i=31;i>=0;--i)if((x>>i)&1){
            if(!d[i])return false;
            x^=d[i];
        }
        return true;
    }
    node operator&(const node b)const {
        node tmpa;memcpy(tmpa.d,d,sizeof d);
        node uda=tmpa,res;
        for(int i=0;i<32;++i)if(b.d[i]){
            int x=b.d[i],sur=0,tag=1;
            for(int j=i;j>=0;--j)if((x>>j)&1){
                if(tmpa.d[j])x^=tmpa.d[j],sur^=uda.d[j];
                else {tmpa.d[j]=x,uda.d[j]=sur,tag=0;break;}//uda.d[i] 指该元素使用的 B_1 中元素 xor 和
            }
            if(tag)res.ins(sur);
        }
        return res;
    }
};

带删除线性基

肯定是离线的啦

考虑求出每个元素的删除时间 ti,按加入时间顺序将元素加入线性基,插入 (v,t) 时,同样依次扫描各个二进制位,执行如下操作:

若当前线性基这一位的删除时间早于 t,将 v 与这一位互换(注意 t 也需要互换),并继续向下插入

否则就异或后正常插入

查询时就将时间早于当前时间的位不考虑即可。

当然可以自然扩展到前缀线性基。

考虑对于原序列的每一段前缀,维护一个前缀线性基。

对于每个二进制位,维护可以贡献它的基底中下标最大的一个。

插入的时候如果存在基底,考虑将插入的数和基底中下标较小的一个继续向下插入,另一个作为当前位的基底。

查询只需要第 r 个前缀线性基中下标大于等于 l 的基底。

线性基与无向图路径

核心:无向图可以走回头路,那么一个环的异或值可以不耗任何代价得到

对于一个无向连通图,有边权,构建 DFS 树后,将所有环的权异或组成一个线性基,具有以下性质

  • 这个线性基只需要所有返祖边所对应简单环异或和即可构建(其他环可以表达为这些环的复合)
  • uv 的所有可能的路径的异或值均可以用这两者的简单路径的异或值与线性基中的值表出,这是因为走到一个环又走回去是可以抵消的,这时候产生贡献的只有环。
  • 对于 uv 所有路径的异或值,用 B 表示所有返祖边构成环的权值组成的线性基,则有将 dudv 加入 B 后,B 的张成空间内的所有元素在原图都能够找到一条 uv 的路径其异或值是这个(特判 0​)

计数的几个结论

  1. Fqn 里选出大小为 k 的线性无关向量组的方案数是:((n)k)q=i=0k1(pnpi)

  2. Fqn 里本质不同 k 维子空间的个数是 ((n)k)q((k)k)q

  3. Fq 里秩为 k 的矩阵个数是 ((n)k)q((m)k)q((k)k)q

    转置原理运用:

    n 个向量张成 k 维空间,相当于是求数 Fq 里有多少个 nk 列矩阵满秩(这里并没有要求每一行不能够相同,也没有要求顺序(也就是讲顺序))

    转置后的等价于有多少个 kn 列矩阵,k 个向量线性无关。

    等价于 Fqn 里选出大小无关的线性无关向量组的方案数 ((n)k)q

相关题目

幸运数字

给定一颗树,点有点权,多次询问,给出 (u,v),求树上 uv 路径选出任意多个点的点权异或和最大值

等价于求出 uv 路径上所有点的点权构成的线性基。

可以利用前缀线性基的方法做一个后缀线性基,详细的说,求出线性基 bi 表示 1i 路径上所有点构成的线性基,每一位贪心保留深度较大的位。

那么每次相当于是拿出 bu,bv 两个线性基里深度 deplca(u,v) 的元素重组一个线性基即可

复杂度 O(nlognlogV)

P 哥的桶

相当于给定 n 个线性基,支持动态在一个线性基里插入一个值,以及询问 [l,r] 的线性基合并后的最大异或和。

线段树暴力维护线性基合并即可,O(nlog3n)

新Nim游戏

考虑从大到小插入线性基,如果插入失败说明此数必选。

正确性:线性基上每一位尽可能让更大的数字占掉不劣。

CF1100F

相当于 P 哥桶的静态版本,每个位置只有一个数。

一个 log2 的做法是考虑是静态的,于是离线询问,分治计算答案,一共执行 O(nlogn) 次插入,单次 log,一共执行 O(q) 个合并,单次 log2

但是更一般地我们采用前缀线性基做即可。

无力回天NOI2017

线性基不支持整体标记,所以我们需要找某些手段将区间修改变成单点修改。

不妨bi=aiai1,每次就变成了单点修改

至于区间 al,al+1,ar 的线性基,等价于 al,bl+1,bl+2br 的线性基,这是显然的(线性组合)。

那么就可以线段树暴力维护 O(nlog3n)

CF959F

线性基性质的扩展。

n 个元素构成的线性基 B,其任意元素 xspan(B)n 个元素里,都恰有 2n|B| 个子序列 xor 和为 x

证明:

我们知道,线性基每个元素是由某些元素异或得到,不妨将其也表达为一个向量(出现/不出现)

插入时,会判断 |B| 个线性基量是否选择,就会被这些线性基元素表达的向量得到一个表达集合。

考虑到有 n|B| 个元素插入失败,他们其实相当于是提供了等效集合的可行性,每个都是选或者可以不选(选上后线性基可以再选一些让其 xor 和为零),不影响答案

所以就是 2n|B|

CF938G

相当于每条边有存在时间,考虑可撤销带权并查集维护线段树分治,维护当前情况的线性基。

每走到一个节点时,保存当前的线性基用来撤销,这部分总 log2

总插入复杂度是 log2n

插入边时,如果不连通,那么利用带权并查集也可以求出新边边权,如果连通那么成环,将其值插入线性基。

而总查询复杂度是 log 的。

所以总复杂度 log2 的。

CF388D

本质上是求有多少个本质不同的线性基满足其最大异或值不超过 n

考虑我们只计数标准型线性基保证不重不漏

那么设 fi,j,0/1 表示 i 的位已经填完,当前线性基已经在前面钦定了 j 个有值的元素,当前这一位如果再加上 2i 能否大于 n

将线性基元素 <i 的位的取值延迟决策是很有意义的。

有如下限制:如果当前位作为某个线性基的最高位,那么这一列仅有这个有值。

转移考虑分类讨论:

  1. 当前不填

    基本转移:fi,j,0·2jfi1,j,0

    1. n 该位为 0

      fi,j,1·2max(0,j1)fi1,j,1,这是已经填过的线性基全部异或起来这一位取零,所以有 2max(0,j1) 种方法

    2. n 该位为 1

      fi,j,1·2max(0,j1)fi1,j,0

      fi,j,1·2max(0,j1)fi1,j,1

      对应一个取奇数个 1,一个取偶数个 1f 能否继续顶住上界。

  2. 当前要填

    基本转移:fi,j,0fi1,j+1,0,这时候相当于该列全是零。

    1. n 该位为零,算了
    2. n 该位为 1,有 fi,j,1fi1,j+1,1

CF1299D

先断开所有与 1 相连的边,那么说明每个连通块至多有 2 条边与 1 相连。

注意到值域很小,本质不同的线性基只有 374 个,可以直接暴力预处理出来,并将其作为状态。

这相当于是求在所有连边方案里有多少个,拿出所有环异或值,异或不出 0 的方案数。

fi,j 为处理完前 i 个连通块,当前线性基状态是 j,预处理 transj,k 表示 j,k 两个线性基合并后如果合法的后继状态。

可以分讨:

  1. 该连通块内部环可以表出 0,则必须全部断掉
  2. 只向这个连通块连一条边,仍然合法
  3. 向这个连通块连两条(如果存在),会产生新环,如果仍然合法,也可以加入 dp 转移。

八纵八横

注意到原图连通,因此可以先求出 dfs 树,然后将所有树上的简单环的异或值插入线性基
接着操作1,2都等价于动态加入/删除某个值
然后问最大 xor 值。

离线下来直接带删 bitset 即可。

CF1603 F

求有多少个长为 n 的非负整数序列 a,满足:

  1. ai[0,2m1]
  2. 不存在一个非空子序列异或和是 x

由于是非空子序列,所以 0 需要特判:

x=0

首先可以注意到这等价于所有元素都可以成功插入线性基,也就是求有多少个 n×m01 矩阵,满足 n 个向量是线性无关向量组

答案即为 i=0n1(2m2i)

x>0

此刻显然所有数字是等价的,因此不妨设 x=1,考虑先求有多少个线性无关向量组与向量 1 线性无关。

枚举向量组大小 k,其实相当于是选出大小为 k+1 的线性无关向量组,并强行钦定第一个是 1,这样就和不含它的形成双射(在不含方案的第一个插入 1),方案数显然是:

i=1k(2m2i)

也有一个容斥解释:可以表出 1 的大小为 k 的线性无关向量组个数

组合证明:

i=0k1(2m2i)(2k1)i=1k1(2m2i)=i=1k(2m2i)

对于 i=0k1(2m2i),相当于 F2m 里选出大小为 k 的线性无关向量组的方案数(注意这不等价于异或线性基(这是未消元的情况,也就是最高位可能相同)

对于 (2k1)i=1k1(2m2i) 相当于从 Fm2 里选出大小为 k 的线性无关向量组且可以表出 v=1 的方案数。

证明:

我们钦定这相当于是首先拿掉 v 后产生的大小为 k1 的线性无关向量组 (a1,a2,,ak1)

考虑如下构造:设最终的向量组是 (b1,b2,bk),可以表出 v

枚举 i[0,k1]Z,我们将构造如下 2i 种方案。

由于 v,a1ak1 两两线性无关,那么将 b1=a1,b2=a2bi=ai,bi+2=ai+1bk=ak1

然后 bi2i 种:v 是否异或上 a1ai,因为两两线性无关,共会产生 2i 种不同的 v,也就是 2ib

那么总的一个 (a1,a2ak1) 可以构造出 i=0k12i=2k1 种不同的 b,且显然不重

不漏也是显然的,我们相当于在整体枚举第一次 v 被表出的时刻

求出基后,我们需要看有多少个 n 向量组张成了 k 维空间,熟悉的朋友显然知道这是:

(nk)2=((n)k)2((k)k)2

所以答案即为:

k=1m((m)k+1)2((n)k)2((k)k)2(2m1)

稍加预处理后可以 O(k+logn) 计算。

校内模拟赛 29th C

相当有意思的题目,也是我不会的题目

首先必然是给 x 减去 1

考虑答案集合的上三角基,也就是标准基,有将其排序后按照 x 二进制分解后选相应位置异或后所得 y,因此我们根据 (xi,yi),(xj,yj) 可以推出 (xixj,yiyj)

这启发我们根据 x 建立线性基,也就是建立线性基,同时维护 rk,num 两个元素,同时插入 (x,y) 时,若最终不能成功插入且 x=0,y0,或者 x0,y=0 都是非法的,无解。

再将这个线性基化为标准基,则我们将 m 个限制化为了 n 个最高位不同的限制。

考虑这样的一对限制 (rki,numi),也就是最高位为 i,当前线性基里存下的排名和数字。

同时对于答案求算,我们都算标准基

这给出了如下信息:

  1. 答案线性基里,highbit(rki) 必须取 highbit(numi) 这一位
  2. 对于 numi 低于最高位且为零的位置 t,也就是 t<highbit(numi),(numi)t=0,这说明我们选择的答案标准基里相应的位置最终异或时这个位必须是零,那么告诉我们参与这个值异或的答案基位置最高位都不能是 t
  3. 对于 t<highbit(numi),(numi)t=1,这说明不参与这个值答案异或的答案基位置最高位不能够是 t

考虑这是否充分(这显然必要)

一个从低到高确定线性基的过程,当我们确定答案基第 i 小数,其最高位为 j 时(首先保证这玩意合法),如果有第一个信息提出的限制,根据已经填了的信息可以直接推知这个值,也就是说这是定值。如果没有第一个信息提出的限制,则有 ji 个二进制位可以任意填写(有 i 个必须是 0 的位,标准基嘛)

所以,根据 rk,num 的信息,我们可以求出数组 can[i,j] 表示答案基第 i 小数其最高位是 j 是否可行,以及 fixedi 表示第 i 小,其最高位和值是否已经确定。

那么有 dp:设 fi,j 表示现在已经填了答案基的前 i 小数字,最高位是 j

考虑转移:

  1. can[i,j]=1
  2. 令转移系数 wfixedi=1w=1,否则 w=2ji
  3. fi,j=wk<jfi1,k

最终答案是考虑所有 rk 限制的最高位 mxh,最少填到这里,最多填到 n,因此答案是:

i=mxhn1j=in1fi,j

difficult-ARC139F-sol

P10707 永恒

考虑先计数标准线性基个数,大小相同的线性基显然对应相同数量的可重集。

fi,j 为填了前 i 位(高位),里面放了 j 个数字,有:

  1. 当前位 m1,则有两个决策:这里放 1,或者前面 j 个放奇数个 1

    有:fi,j=fi+1,j1+fi+1,j·2j1,注意 j=0 时不进行转移。

  2. 当前位 m0,则我们只能固定前面填的元素这一位有偶数个 1

    有:fi,j=fi+1,j·2j1j=0 时取 1

有了这个,我们可以知道 dpi 表示大小为 i 的,最大值为 m 的线性基个数。

现在考虑设 gi 为大小为 i 的线性基对应的序列个数(注意是恰好表出)。

由于这个是可重集,考虑dp(但是如果你枚举去重后的集合大小,利用公式算,然后可重就随意附加这样来就错完了,因为公式那个不计顺序(也就是顺序不同算不同),很难变成集合形式)。

考虑容斥,那么就还需要一个 hi,j 表示大小为 i 的线性基的大小为 j 的子基个数。

(这里称 AB 的子基当且仅当 span(A)\subspan(B)

考虑从前往后转移,如果我舍弃当前这个最小基的元素,它就可以让前面的位随意的异或上它且由于线性无关可以产生不重复不漏的方案(注意这也是标准基)。

于是就有 hi,j=hi1,j+hi1,j12ij

根据插板法,那就有 gi=(2i+n1n)j<ihi,jgj

答案即为 f0,igi

posted @   spdarkle  阅读(54)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示