2019牛客国庆集训派对day4 C Intersection 线性基

题目链接:

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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值