首先看一道题:洛谷 P3812 【模板】线性基
题目名称已经说明了算法是什么,毕竟是一道模板题对吧。。。
线性基是什么?
哈?学过线性代数或者高斯消元的都应该知道吧。。。
不知道的左转出门自行百度。。。
或者参考这两篇博客:
在竞赛中,提到线性基,一般是指异或线性基。
实际上上面两篇博客已经把该奖的都差不多讲完了。
其实线性基还可以合并。
两个线性基合并就是暴力把某个线性基强行插入另外一个线性基。
代码的话,可以写成结构体重载加法:
struct Linear_Basis{
long long base[MAXN]={0};
bool zero=false;
bool insert(long long x){
for(int i=63;~i;i--)if(x&(1LL<<i)){
if(!base[i]){base[i]=x;return true;}
else x^=base[i];
}
zero=true;
return false;
}
friend Linear_Basis operator +(const Linear_Basis &u,const Linear_Basis &v){
Linear_Basis ret;
for(int i=63;~i;i--){
if(u.base[i])ret.insert(u.base[i]);
if(v.base[i])ret.insert(v.base[i]);
}
ret.zero=u.zero|v.zero;
return ret;
}
};至此,基本上线性基的基本操作都搞完了。
是时候拿出犹大练手题了!
板子题,放个代码在这吧。
#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 70
using namespace std;
int n;
int top=0;
long long stack[MAXN];
struct Linear_Basis{
long long base[MAXN]={0};
bool zero=false;
void init(){
zero=false;
for(int i=0;i<=64;i++)base[i]=0;
}
bool insert(long long x){
for(int i=63;~i;i--)if(x&(1LL<<i)){
if(!base[i]){base[i]=x;return true;}
else x^=base[i];
}
zero=true;
return false;
}
bool check(long long x){
if(!x)return zero;
for(int i=63;~i;i--)if(x&(1LL<<i)){
if(!base[i])return false;
x^=base[i];
}
return true;
}
long long query_max(long long s){
for(int i=63;~i;i--)s=max(s,s^base[i]);
return s;
}
long long query_min(){
if(zero)return 0;
for(int i=0;i<=63;i++)if(base[i])return base[i];
}
long long query(long long k){
long long s=0;
k-=zero;
if(!k)return 0;
for(int i=0;i<=63;i++){
for(int j=i-1;~j;j--)if(base[i]&(1LL<<j))base[i]^=base[j];
if(base[i])stack[++top]=base[i];
}
if(k>=(1LL<<(top-1)))return -1;
while(top){
if(k&(1LL<<(top-1)))s^=stack[top];
stack[top--]=0;
}
return s;
}
friend Linear_Basis operator +(const Linear_Basis &u,const Linear_Basis &v){
Linear_Basis ret;
for(int i=63;~i;i--){
if(u.base[i])ret.insert(u.base[i]);
if(v.base[i])ret.insert(v.base[i]);
}
ret.zero=u.zero|v.zero;
return ret;
}
}a;
char tp[100000],*p1=tp,*p2=tp;
inline char get_char(){
return p1==p2&&(p2=(p1=tp)+fread(tp,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline long long read(){
long long date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=get_char();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=get_char();}
return date*w;
}
void init(){
long long x;
n=read();
for(int i=1;i<=n;i++){
x=read();
a.insert(x);
}
}
int main(){
init();
printf("%lld\n",a.query_max(0));
return 0;
}这是一道基本题。
就是个游戏的变形。
这是一道在线性代数里的线性基,就是正常的加减法线性基。

京公网安备 11010502036488号