线性基入门
Posted fridayfang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线性基入门相关的知识,希望对你有一定的参考价值。
线性基入门
简要讲解
xor下的线性基:
线性基求法:
从高位向低位求,如果控制i位的线性基存在,则a[k]^=p[i]
否则 p[i] = a[k];break;
进一步,将除线性基p[i]外的线性基的i位变为0;则得到元素最小的线性基;求第k小;
注意当元素存在冗余,则可以异或生成0;反之,不能生成0
将k进行2进制表示,则可对应相应的线性基进行异或线性基的概念类似于空间张成,即通过最少的元素能张成异或运算下的整个空间
参考博客
例题HDU3949
code
#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("O3")
#define ll long long
#define ull unsigned long long
#define db(x) cout<<#x"=["<<(x)<<"]"<<endl
#define CL(a,b) memset(a,b,sizeof(a))
#define fast() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define fr0(i,m) for(int i=0;i<m;i++)
#define fr1(i,m) for(int i=1;i<=m;i++)
//author:fridayfang
//date:19 7月 07
const double esp=1e-8;
const int mod=1e9+7;
const double pi=acos(-1);
const int inf=0x3f3f3f3f;
const int maxn = 1e4 + 5;
const int maxm = 1e6+5;
ll a[maxn];
ll p[64];
int to[100];//
ll t,n,q;
int getBase()//处理处理出线性基
CL(p,0);//先要清0
for(ll i=1;i<=n;i++)
for(int j=63;j>=0;j--)
if((a[i]>>j)&1)
if(!p[j])p[j] = a[i]; break;
a[i]^=p[j];
// 更小的线性基
int cnt = 0;
for(int j=0;j<=63;j++)
if(!p[j]) continue;
for(int i=j+1;i<=63;i++)
if((p[i]>>j)&1) p[i] = p[i]^p[j];
to[cnt++]=j;
return cnt;//cnt是线性基的个数 to[0]...to[cnt-1]有正确的映射
ll getK(ll k,int bound)//除0外的最k小
int t = 0;
ll tmp = k;
ll ans = 0;
while(tmp)
if(t>=bound) return -1;
if(tmp&1) ans^=p[to[t]];
tmp = tmp>>1;
t++;
return ans;
int main()
fast();cin>>t;
for(ll i=1;i<=t;i++)
cout<<"Case #"<<i<<":\\n";
cin>>n;
for(ll k=1;k<=n;k++) cin>>a[k];
int cnt = getBase();
int t = (cnt==(int)n)?0:1;//不等表示有冗余,则可表示0;此时第k小时第k-1小
cin>>q;
ll k;
for(ll s=1;s<=q;s++)
cin>>k; k-=t;
cout<<getK(k,cnt)<<endl;
return 0;
以上是关于线性基入门的主要内容,如果未能解决你的问题,请参考以下文章