P3812
【模板】线性基
实际上是将向量转化为 01 矩阵后高斯消元简化基底。
这个板子只包括查询最大。我们再加一些奇奇怪怪的东西。
向线性基中插入一个数:
1
2
3
4
5
6inline void ins(ll x) {
for(ll i=51;i>=0;i--) {
if((x>>i)&1) {if(!p[i]) {p[i]=x;break;}else x^=p[i];}
if(x==0) {tag_zero=1;return;}
}
}查询 $x$ 是否能被表出:
1
2
3inline bool ask(ll x) {
for(ll i=51;i>=0;i--) {if((x>>i)&1) x^=p[i];}return x==0;
}查询可以被异或出的最大值:
1
2
3
4
5inline ll askmax() {
ll res=0;
for(ll i=51;i>=0;i--) {if((res^p[i])>res) res^=p[i];}
return res;
}查询最小值:
1
2
3
4inline ll askmin() {
if(tag_zero) return 0;
for(ll i=0;i<=51;i++) if(p[i]) return p[i];
}这里记得在插入的时候记录 0 出现的标签。
查询 $k$ 小与排名:
首先我们需要
rebuild
一个 $d$ 数组:1
2
3
4
5
6
7inline void Rebuild() {
cnt=0;
for(ll i=51;i>=0;i--) {
for(ll j=i-1;j>=0;j--) {if((p[i]>>j)&1) p[i]^=p[j];}
}
for(ll i=0;i<=51;i++) if(p[i]) d[cnt++]=p[i];
}稍微解释一下这个东西在干什么。实际上这个东西在高斯消元,把原本的倒三角形的矩阵尽量消到一个行向量中只有一个值为 1。
接下来我们查询 $k$ 小。
1
2
3
4
5
6inline ll Kth(ll k) {
if(k-tag_zero==0) return 0;k-=tag_zero;
if(k>=(1ll<<cnt)) return -1;ll res=0;
for(ll i=51;i>=0;i--) if((k>>i)&1) res^=d[i];
return res;
}背板当然是最方便的。查询排名:
1
2
3
4inline ll Rk(ll x) {
ll res=0;for(ll i=cnt-1;i>=0;i--) if(x>=d[i]) {res+=(1<<i);x^=d[i];}
return res+tag_zero;
}
没了。
代码:
1 |
|