题目链接:
https://ac.nowcoder.com/acm/contest/1109/C
题意:
有一个集合A={a1,a2,a3.....an}, 一个集合B={b1,b2,......bm}.
问有多少个数字能通过A的子集进行异或运算得出并且也能通过B的子集异或运算得出。子集可以是空集
比如 A={1,2},B={1,3}
A 的子集有{} ,{1},{2},{1,2} 异或运算能得到: 0,1,2,3
B 的子集有{},{1},{3},{1,3} 异或运算能得到: 0,1,3,2
A和B都能得到:0,1,2,3.
那么输出4
题解:
求A的线性基和B的线性基交集的秩,假设为x,那么答案就是 2的x次方。
线性基交集的秩=A的线性基的秩+B的线性基的秩-A和B线性基的并的秩
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=70;
ll aa[maxn],bb[maxn];
struct PPP{
ll p[70];
const int N=62;
vector<ll> v;
int zhi;
void init(){
zhi=0;
memset(p,0,sizeof(p));
}
void insert(ll *a,int st,int en){
for(int i=st;i<=en;++i)
for(int j=N;j>=0;--j)
if(a[i]&(1LL<<j))
if(p[j]) a[i]^=p[j];
else{
p[j]=a[i];
break;
}
v.clear();
zhi=0;
for(int i=0;i<=N;++i) if(p[i]) v.push_back(p[i]),++zhi;
}
}a,b;
int main(){
int n;
while(scanf("%d",&n)!=EOF){
a.init();b.init();
for(int i=0;i<n;i++) scanf("%lld",&aa[i]);
for(int i=0;i<n;i++) scanf("%lld",&bb[i]);
a.insert(aa,0,n-1);
b.insert(bb,0,n-1);
PPP c=a;
c.insert(b.p,0,62);
ll cnt=a.zhi+b.zhi-c.zhi;
ll ans=1LL<<cnt;
printf("%lld\n",ans);
}
return 0;
}