[笔记]线性基

比较好懂的博客

里面有比较多的题型还有证明

注意

  • long long
  • 成功插入线性基之后记得返回

线性基用来干什么

维护一个序列的异或值:

\(d[]\)为序列\(a[]\)的线性基,那么:

  1. \(d[]\)中任意一些元素异或的集合与\(a[]\)中任意一些元素异或的集合相同
  2. \(d[]\)中任意一些元素异或不为0
  3. \(d[]\)是所有满足条件1的集合中最小的

其中\(d[i]\)的第\(i\)位上为1

插入

从高位往低位找

  • 如果当前为没有值,直接插入并返回
  • 否则,把\(x\)异或上\(d[i]\),继续找
int INS(LL x){
	tep(i,60,0){
		if(!((x>>i)&1))continue;
		if(!d[i]){
			d[i]=x;
			cnt++;//记录线性基中有多少元素
			return 1;
		}
		x^=d[i];
	}
	return 0;//返回值表示是否能够成功插入(如果原来的线性基中已经存在某一些
			 //数异或和为X,那么x就没有必要被插入。这个时候a[]异或可以得到0,需要特判
}

查询

最大值

从高位往低位扫,如果\(ans\oplus d[i]>ans\),那么把\(ans\)异或上\(d[i]\),否则说明\(ans\)的第\(i\)为已经有\(1\),异或\(d[i]\)只会使答案变小,就skip

最小值

就是\(d[]\)里面最小的

\(k\)

就是求所有能异或得到的数中第\(k\)小的那个

传送门


Part1

先重构\(d[]\),使得对于每一个\(i\),最多只有一个\(d[j]\)的第\(i\)位上为1

rep(i,1,maxn)rep(j,0,i-1){
		if((d[i]>>j)&1)d[i]^=d[j];
}

正确性:

\(d[i]\oplus d[j]\)后,线性基里的元素从\(d[i],d[j]\)变成了\(d[i]\oplus d[j],d[j]\),可以发现,这两个元素异或得到的集合还是不变的,所以整个集合的异或值也不会变


Part2

先上代码

rep(i,0,60){
		if(d[i]!=0){
			if(k&1)ans^=d[i];
			k/=2;
		}
	}

没想到吧,二进制真是奇妙,自己琢磨吧


Part3 Notice

注意判断0。如果原序列可以异或得到0,那么k要减1

猴啦上代码啦

Code

#include<bits/stdc++.h>
#define rep(X,A,B) for(int X=A;X<=B;X++)
#define tep(X,A,B) for(int X=A;X>=B;X--)
#define LL long long
const int N=1000010;
const int M=2000010;
const int maxn=60;
using namespace std;

void read(int &x){
	scanf("%d",&x);
}

int n,Q,flg,cnt=0;
LL d[N],tot;

int INS(LL x){
	tep(i,60,0){
		if(!((x>>i)&1))continue;
		if(!d[i]){
			d[i]=x;
			cnt++;
			return 1;
		}
		x^=d[i];
	}
	return 0;
}

void READ(){
	LL x;
	flg=1;
	cnt=0;
	read(n);
	rep(i,0,60)d[i]=0;
	
	rep(i,1,n)scanf("%lld",&x),flg&=INS(x);
	rep(i,1,maxn)rep(j,0,i-1){
		if((d[i]>>j)&1)d[i]^=d[j];
	}
	tot=1;
	rep(i,1,cnt)tot*=2;tot--;
	read(Q);
}

LL SOLVE(){
	LL k,ans=0;
	scanf("%lld",&k);
	if(!flg)k--;
	if(k>tot)return -1;
	rep(i,0,60){
		if(d[i]!=0){
			if(k&1)ans^=d[i];
			k/=2;
		}
	}
	return ans;
}

int main(){
	int T;
	read(T);
	rep(op,1,T){
		printf("Case #%d:\n",op);
		READ();
		while(Q--)printf("%lld\n",SOLVE());
	}
	return 0;
}
posted @ 2019-10-20 15:17  硫氯  阅读(83)  评论(0编辑  收藏  举报