线性基求交与求并

说明

先说明一下这里的求交与求并分别是什么意思。就是有两个线性空间 V 1 V_1 V1 V 2 V_2 V2,求出这两个空间的交与并。当然OI中的线性空间大部分是指异或操作下的,也就是常说的线性基。
如下所说的,都是异或的线性基,不区分加号与异或,即 ∑ x i = x 1 ⊕ x 2 . . . ⊕ x 3 \sum x_i = x_1 \oplus x_2 ... \oplus x_3 xi=x1x2...x3
当然可以扩展到任意线性空间,大致方法不变。

求交

明显答案也是一个线性基。
那么我们还需要如下引理:
{ α i = 1 − x } \{\alpha_{i= 1 - x}\} {αi=1x} V 1 V_1 V1的一组线性基, { β i = 1 − y } \{\beta_{i= 1 - y}\} {βi=1y} V 2 V_2 V2的一组线性基。设 W W W { β } \{\beta\} {β}中在 V 1 V_1 V1的基,如果 α ⋃ { β ∖ W } \alpha \bigcup\{\beta \setminus{W}\} α{βW}线性无关,那么 W W W就是交的线性基。
从而可以得到:

如果 β i \beta_i βi能被 { α i = 1 − x } \{\alpha_{i=1-x}\} {αi=1x} β j = 1... i − 1 \beta_{j = 1 ... i - 1} βj=1...i1线性表示出来,我们可以把 ⨁ i = 1 x α i \bigoplus_{i = 1}^{x}\alpha_i i=1xαi或者 ⨁ j = 1 i − 1 β j \bigoplus_{j=1}^{i-1}\beta_j j=1i1βj(注意要么加入 α \alpha α要么加入 β \beta β)加入答案的线性基中。
代码如下:

LinearBasis Merge(LinearBasis A,LinearBasis B) {
	LinearBasis All , C , D;
	All.clear();
	C.clear();
	D.clear();
	for (int i = 60;i >= 0;i--) {
		All.basis[i] = A.basis[i];
		D.basis[i] = 1ll << i;
	}
	for (int i = 60; i >= 0; i--) {
		if (B.basis[i]) {
			ll v = B.basis[i] , k = 0;
			bool can = true;
			for (int j = 60; j >= 0; j--) {
				if (v & (1ll << j)) {
					if (All.basis[j]) {
						v ^= All.basis[j];
						k ^= D.basis[j];
					} else {
						can = false;
						All.basis[j] = v;
						D.basis[j] = k;
						break;
					}
				}
			}

			if (can) {
				ll v = 0;
				for (int j = 60; j >= 0; j--) {
					if (k & (1ll << j)) {
						v ^= A.basis[j];
					}
				}
				C.insert(v);
			}
		}
	}
	C.build();
	return C;
}

同样的,如下代码也可以:

LinearBasis Merge(LinearBasis A,LinearBasis B) {
	LinearBasis All , C , D;
	All.clear();
	C.clear();
	D.clear();
	for (int i = 60;i >= 0;i--) All.basis[i] = A.basis[i];
	
	for (int i = 60; i >= 0; i--) {
		if (B.basis[i]) {
			ll v = B.basis[i] , k = 1ll << i;
			bool can = true;
			for (int j = 60; j >= 0; j--) {
				if (v & (1ll << j)) {
					if (All.basis[j]) {
						v ^= All.basis[j];
						k ^= D.basis[j];
					} else {
						can = false;
						All.basis[j] = v;
						D.basis[j] = k;
						break;
					}
				}
			}

			if (can) {
				ll v = 0;
				for (int j = 60; j >= 0; j--) {
					if (k & (1ll << j)) {
						v ^= B.basis[j];
					}
				}
				C.insert(v);
			}
		}
	}
	C.build();
	return C;
}

注意区别。

求并

通过容斥原理将并转化为交即可。

你可能感兴趣的:(总结,省选,线性基)