【模板】线性基模板
数学太差,直接线性基当数据结构用orz
表示数集[1,2^k-1] 表示一个异或集合
可以说是将原数集压缩
性质:(直接抄的orz,虽然也不是特别懂)
1.设线性基的异或集合中不存在0。
2.线性基的异或集合中每个元素的异或方案唯一,其实这个跟性质1是等价的。
3.线性基二进制最高位互不相同。
4.如果线性基是满的,它的异或集合为[1,2n−1]。
5.线性基中元素互相异或,异或集合不变。
1插入
插入某数,从高位到低位扫其二进制位上为1的数,扫到某位,这位上位0直接修改值为这个数,否则这个数与这个位上的值异或。最后结果要么为0,要么被加入了线性基void insert(int x) { for(int i=31;i>=0;i++) { if((x&(1<<i)) { if(!a[i]) { a[i]=x; break; } else x^=a[i]; } } }
2合并
暴力一个位一个位合并xxj merge(const xxj &n1,const xxj &n2) { xxj ans = n1; for(int i=0;i<=31;i++) { if(n2.a[i]) ans.insert(n2.a[i]); } return ans; }
3查询最大值
从高位一个一个异或,如果可以使ans异或某位后变大就异或一下。int query_max() { int ans =0; for(int i=31;i>=0;i--) { if((ans^(a[i]))>ans) ans^=a[i]; } return ans; }
4查询最小值
从最低位开始扫,扫到的第一个数int query_min(int i=0;i<=60;i++) { for(int i=0;i<=31;i++) { if(a[i]) return a[i]; } return 0; }主要某道题急着要用线性基,等有时间认真学一波线性基。