线性基总结(其实就是我的模板)
Posted philo-zhou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线性基总结(其实就是我的模板)相关的知识,希望对你有一定的参考价值。
想知道线性基直接看大佬的https://blog.sengxian.com/algorithms/linear-basis, 我就是弄下我常用的操作。
定义
学过线代里面的“基向量”,基向量说的就是一组可以表示整个空间的向量。比如在三维空间中一个基向量就是(1,0,0) (0,1,0) (0,0,1)。线性基的定义也类似,给你一个数组a[ ],它的线性基就是一组可以表示数组a中任意一个数的一个数组p[ ]。这个表示的意思就和前面的基向量表示的意思类似,是通过p中几个元素的异或得到a中的任意一个元素。
性质
1 原序列里面的任意一个数都可以由线性基里面的一些数异或得到
2 线性基里面的任意一些数异或起来都不能得到0
3 线性基里面的数的个数唯一,并且在保持性质一的前提下,数的个数是最少的
#include<bits/stdc++.h> #define mp make_pair #define met(a, b) memset(a, b, sizeof(a)) #define ll long long using namespace std; ll p[70], newp[70], cnt; void getp(ll x) //构建 for(ll i = 63; i >= 0; i--) if(!(x>>i)) continue; if(!p[i]) p[i] = x; break; x ^= p[i]; ll getmax() //求异或最大值 ll ans = 0; for(int i = 63; i >= 0; i--) if((ans ^ p[i]) > ans) ans ^= p[i]; return ans; ll getmin() //求异或最小值 for(int i = 0; i <= 63; i++) if(p[i]) return p[i]; return 0; bool judge(ll x) //判断x是不是数组a中的 for(ll i = 63; i >= 0; i--) if(x>>i) x ^= p[i]; if(!x) return 1; return 0; void rebuild() //求第k小的准备工作 cnt = 0; for(ll i = 63; i >= 0; i --) for(ll j = i - 1; j >= 0; j --) if(p[i] & (1 << j)) p[i] ^= p[j]; for(ll i = 0; i <= 63; i ++) if(p[i]) newp[cnt++] = p[i]; ll getans(ll k) //求第k小 if(k >= (1ll << cnt)) return -1; ll ret = 0; for(ll i = 63; i >= 0; i --) if(k & (1ll << i)) ret ^= newp[i]; return ret; int main() int n; cin >> n; for(int i = 1; i <= n; i++) ll x; cin >> x; getp(x); rebuild(); int m; cin >> m; while(m--) ll k; cin >> k; if(n != cnt) k--; //注意这个 cout << getans(k) << endl; return 0;
以上是关于线性基总结(其实就是我的模板)的主要内容,如果未能解决你的问题,请参考以下文章