牛客多校一 H.XOR(线性基)

题目要求求出所有子集异或和为0时子集的大小之和。通过计算每个数在子集中出现的次数来解决问题。首先求出初始的线性基,然后只考虑线性基外的元素,因为线性基外的元素有且只有一种方式与其他元素异或和为0。对于基外的每个元素,有2n-r-1种选择子集的方式。接着考虑基中的元素,枚举基中的元素并判断是否能插入新的线性基,以确定其对方案数的影响。通过这种方法,避免重复求线性基,提高了效率。
摘要由CSDN通过智能技术生成

原题地址:https://ac.nowcoder.com/acm/contest/881/H

核心知识点:
1.对于任何在线性基外的元素,在基内有且只有一种方法使得两者的异或和为0
2.一组数可能会有多种线性基的方案,但是不变的是线性基的数量。

题意:给出一个集合,让求所有子集异或和为0时,子集的大小之和,

思路:首先直接计算子集的大小之和不是很好下手,可以将问题转化为求每个数在子集中出现的次数,然后算n个数产生的总贡献即可。

然后对于这种异或和问题,首选用异或和处理问题。
我们对一开始的n个数字求一次线性基,假如得到一个大小为r的基,那么对于基外的n-r个元素,我们假设选取数字x计算其贡献,选了x之后还剩余n-r-1个元素在基外,那么对于数字x就有 2 n − r − 1 2^{n-r-1} 2nr1种方案选择x的子集。

说明一下为什么只用基外的元素来挑选方案。
因为假设你在选中了x之外还挑选了基内的某些元素试图找到更多的方案数,如果你选中的元素中本来就不是使得x的异或和为0的话,那么你加上这个元素就不可能再使得异或为0了,因为由线性基得性质可得,经过消元后得线性基,第i位为1的最多只会有一个数,如果你选择了这个数,就不可能再消掉这位上的1了。
如果你选中的本来就是使x异或为0的元素,那么你会发现最后挑出来的使同一种方案。
所以选择方案只需要用基外的元素即可。

现在挑完了n-r个基外元素,考虑基中的r个元素的贡献。
我们可以枚举基中的元素,对除了选中的数之外的n-1个数求一次线性基,判断选中的元素还能否插入到新求得线性基中,如果能,说明选中了当前元素就不可能会有异或和为0的方案。如果能就会产生 2 n − r − 1 2^{n-r-1} 2nr1种方案,理由同上。至于基的数量也是r,参考知识点2.
最后,关于求n-1个元素的线性基,不用每次真的再去求一遍,求出n-r个元素的基,每次重新插入r-1个元素即可。

#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值