线性基
算法理解
可以看这篇讲解
然后注意深入理解为什么线性基插入顺序不会影响线性基的大小和作用
T1:
结论(性质):
在线性基中,任意选取一些数的异或和都不相同
即任意选取大小为 \(k\) 的线性基中的任意个值的异或和有 \(2^k\) 种
证明:
如果选出来的集合有交:
假设:
\(x \oplus y \oplus ...=z\)
\(x \oplus h \oplus ...=z\)
因为集合都有相同的 \(x\) ,则 \((y \oplus ...) \oplus (h \oplus ...)=0\) 不符合线性基的性质线性基的任意数的异或和不等于 0,不成立
如果选出来的集合无交:
考虑异或出来的数 \(z\) 的有 1 的最高位 \(w\),它必然是由 \(p[w]\) 异或而来的,所以集合一定有交,不成立
证毕
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=50,mod=2008;
int n,cnt,m;
int a[N+5],p[N+5];
int change(char s[N+5]){
int res=0,w=0;
for(int i=n-1;i>=0;i--){
if(s[w++]=='O') res+=1ll<<i;
}
return res;
}
void ins(int x){
// printf("%d\n",x);
for(int i=N;i>=0;i--){
if(x&(1ll<<i)){
if(!p[i]){
p[i]=x;
cnt++;
break;
}
else x^=p[i];
}
}
}
int query(){
int res=0;
for(int i=N;i>=0;i--){
if((res^p[i])>res) res^=p[i];
}
return res;
}
signed main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=m;i++){
char s[N+5];
scanf("%s",s);
ins(change(s));
}
printf("%lld\n",(1ll<<cnt)%mod);
}
T2:
直接按价值排序
注意深入理解为什么线性基插入顺序不会影响线性基的大小和作用
直接切了
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int M=62,N=1005;
int n,ans;
int p[N];
struct dot{
int x,v;
}a[N];
bool cmp(dot x,dot y){
return x.v>y.v;
}
void ins(int x,int v){
for(int i=M;i>=0;i--){
if(x&(1ll<<i)){
if(!p[i]){
p[i]=x;
ans+=v;
break;
}
else x^=p[i];
}
}
}
signed main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%lld%lld",&a[i].x,&a[i].v);
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++){
ins(a[i].x,a[i].v);
}
printf("%lld\n",ans);
}

浙公网安备 33010602011771号