集合异或

集合异或 ⁡ \operatorname{集合异或}

题目链接: ybtoj 20036 ⁡ \operatorname{ybtoj\ 20036} ybtoj 20036

题目

tt 喜欢数据结构,可是他面前有一道难题,他一下子就秒切了,为了提高你的水平,他把这道题给了你:

给定一个长度为 n n n 的多重集 A A A,求出这个集合所有的非空子集中的所有元素和的异或和。

输入

第一行一个数 n n n

然后 n n n 行,每行 1 1 1 个数可重集 A A A 中的一个元素。

注意使用 scanf 或 cin 输入,不要使用快读输入 。

输出

输出一行一个数表示答案。

样例输入1

2
1 3

样例输出1

6

样例解释1

{ 1 , 3 } \{1,3\} {1,3} 集合的所有非空子集, { 1 } , { 3 } , { 1 , 3 } \{1\},\{3\},\{1,3\} {1},{3},{1,3},答案: 1 ⊕ 3 ⊕ ( 1 + 3 ) = 6 1\oplus 3\oplus (1+3)=6 13(1+3)=6

⊕ \oplus 指异或操作。

样例2~5

在本题附加文件

数据范围

对于 20 % 20\% 20% 的数据,保证在样例中出现。

对于 100 % 100\% 100% 的数据, ∀ x ∈ A , x > 0 , 1 < n < 1000 , ∑ A i ≤ 2 × 1 0 6 \forall x\in A,x>0,1<n<1000,\sum A_i\leq 2\times 10^6 xA,x>0,1<n<1000,Ai2×106

提示

多重集
子集
异或

思路

这道题是一道数据结构体。
用 bitset 来做。

题目是要每个子集所有数的和异或起来,那我们可以用一个 bitset 数组 a n s ans ans 来记录和为 i i i 的集合们对答案有没有贡献。
(因为是异或,所以出现了偶数次就是没有贡献,被抵消了,否则就有贡献,抵消完之后剩下一个)

那每一次有一个新的数 x x xans ^= ans << x
(就是之前有的 1 1 1 全部都右移了 x x x 位,就是都加了 x x x,再跟原来不加的异或)

然后最后把 a n s ans ans 中是 1 1 1 的位的位异或起来,就是答案了。

代码

#include<cstdio>
#include<bitset>

using namespace std;

int n, a, sum, answer;
bitset <2000000> ans;

int main() {
//	freopen("segment.in", "r", stdin);
//	freopen("segment.out", "w", stdout);
	
	scanf("%d", &n);
	
	ans.set(0, 1);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a);
		sum += a;
		ans ^= ans << a;
	}
	
	for (int i = 1; i <= sum; i++)
		answer ^= ans.test(i) * i;//把是1的位的位异或起来
	
	printf("%d", answer);
	
	fclose(stdin);
	fclose(stdout);
	
	return 0;
} 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值