码迷,mamicode.com
首页 > 其他好文 > 详细

线性基

时间:2020-01-30 10:04:09      阅读:80      评论:0      收藏:0      [点我收藏+]

标签:多个   因此   ret   strong   最大   trie   pre   异或   操作   

线性基

概述

线性基,是一个线性空间(二元运算为异或)的极大线性无关子集

用于解决一系列集合异或和最值问题

注意与Trie树区别在于可以多个

性质

1.表示任意一个异或和方式唯一
2.所有子集异或和不为0
3.线性基内高位各不相同
4.\(tot\)个位置可以表示\(2^{tot}\)种异或和

实现

先做一些定义
\(p_i\)表示以第\(i\)位为最高位的基底
\(dig_i\)表示从低到高第\(i\)个有值的位置

插入

从高到低考虑\(x\)的每一位(其实是当前的最高位)
若这一位\(p\)没有值直接插入
否则异或上这一位的\(p\)
那么这一位以上的位均会变成0,并且如果他能插入应为线性无关的因此保证可正确性
操作直到成功插入或\(x=1\)后停止(线性有关)

inline char Insert(re ll x){re int i;for(i=DIGIT;x;--i)if((x>>i)&1){if(p[i])x^=p[i];else return p[i]=x,1;}return 0;}

求子集最大/最小异或和

对最大:从高向低位贪心(线性基性质导致低位不会影响高位)能拼凑出当前位就拼

对最小:这个直接找到最高位最低的基即可

inline ll Find_max(void){
    re int i;re ll res=0;
    for(i=DIGIT;~i;--i)if((res^p[i])>res)res^=p[i];
    return res;
}
inline ll Find_min(void){
    re int i;re ll res=0;
    for(i=0;i<=DIGIT;++i)if(p[i])return p[i];
}

高斯消元

把线性基化成每一个向量最多含一位的形式

方便比较

去重第k小

直接二进制拆位后拼凑即可

这是不用\(dig\)预处理的(同理)

inline ll Find_kth(re ll k){
    re int i,x;
    if(n^tot)--k;if(k>=(1ll<<tot))return -1;
    ans=0,x=tot;for(i=DIGIT;~i;--i)if(p[i])if(((k>>(--x))&1)^((ans>>i)&1))ans^=p[i];
    return ans;
}

线性基

标签:多个   因此   ret   strong   最大   trie   pre   异或   操作   

原文地址:https://www.cnblogs.com/66t6/p/12241844.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!