线性基汇总

线性基


  • 定义:

    ​ 在 mod 2的意义下,有n个长度为m的向量,这n个向量的线性基为其所组成的线性空间V的基底。

  • 构造:

    ​ 我们考虑用增量法来构造线性基。假如现在要插入一个向量,从左向右不断消去1,直到出现了第一个无法消去的1,说明这个向量无法用现在的几组基底表示出来,所以将其插入线性基。(普通的线性基构造按照这样写就可以了,不过我们有一种更优秀的写法,它会有很多不错的性质)。

    const int MAXN=31;
    int a[MAXN+5];
    void insert(int v){
    	for(int i=MAXN;i>=0;--i) if((v>>i)&1){
    		if(a[i]) v^=a[i];
    		else{
    			for(int j=i-1;j>=0;--j)
    				if((v>>j)&1) v^=a[j];
    			for(int j=i+1;j<=MAXN;++j)
    				if((a[j]>>i)&1) a[j]^=v;
    			a[i]=v;
    			break; 
    		}
    	}
    }
    
  • 本质不同的子集异或和计数:

    给定n个数,第i个数位 a i a_i ai,询问其中有多少个本质不同的子集异或和。n ≤ 1 0 5 \le10^5 105 a i ≤ 1 0 9 a_i\le10^9 ai109

    • 首先考虑线性基是什么?线性基是给定的n个向量通过任意变换形成的线性空间的基底,也就是说线性基任意变化形成的线性空间与之前的是完全一致的。那么就很OK了啊,我们求出线性基,如果基底数量为m,那么答案就是 2 m 2^m 2m
  • 最大/最小子集异或和:

    给定n个数,第i个数位 a i a_i ai,询问最大子集异或和与最小子集异或和。n ≤ 1 0 5 \le10^5 105 a i ≤ 1 0 9 a_i\le10^9 ai109

    • 求最大:贪心地考虑,在二进制下,高位为1一定更优。所以我们从左向右(即从高位向低位)选,如果当前值xor当前基底之后答案变大,就xor。最后得到的一定是最大值。
    • 求最小:不要陷入最大的闭合思路里面。求最小值涉及到了用了上面构造方法构造出来的线性基的性质。(1)如果在插入一个数的时候,发现这个数无法被插入线性基,说明已经可以变换出这个数了,那么最小值一定为0。(2)如果没有第一种情况,那么最小值一定是线性基里最小的数。
  • 异或和为零的子集计数:

    给定n个数,第i个数位 a i a_i ai,询问有多少个子集是满足异或和为零的。n ≤ 1 0 5 \le10^5 105 a i ≤ 1 0 9 a_i\le10^9 ai109

    • 考虑假如一个向量无法插入线性基,那么在线性基内一定有一个子集异或和等价于它,所以会形成一个异或和为0的子集。一般的,线性基外的所有向量,任意组合的子集形成的向量一定在线性基内可以体现,所以异或和为0的子集个数应该是 2 k 2^k 2k,k为线性基外的向量数。

刷题榜

[HDU3949] 子集异或第K大(https://blog.csdn.net/qq_39759315/article/details/88789906)

[BZOJ2844] 子集异或的权值出现次数(https://blog.csdn.net/qq_39759315/article/details/88789872)

[BZOJ4568] 线性基+倍增暴力维护(https://blog.csdn.net/qq_39759315/article/details/88789880)

[BZOJ3569] 线性基判断连通性(https://blog.csdn.net/qq_39759315/article/details/88789961)

[BZOJ2115] 线性基+dfs树(https://blog.csdn.net/qq_39759315/article/details/88789957)

[BZOJ3105] 线性基+博弈论(https://blog.csdn.net/qq_39759315/article/details/88789941)

大概就先到这里了,多加练习才是硬道理!

你可能感兴趣的:(线性代数)