题目描述
小呆开始研究集合论了,他提出了关于一个数集四个问题:
1.子集的异或和的算术和。
2.子集的异或和的异或和。
3.子集的算术和的算术和。
4.子集的算术和的异或和。
目前为止,小呆已经解决了前三个问题,还剩下最后一个问题还没有解决,他决定把这个问题交给你,未来的集训队队员来实现。
a
i
>
0
a_i\gt 0
ai>0,
1
<
n
<
1000
1\lt n\lt 1000
1<n<1000,
∑
a
i
≤
2000000
\sum a_i\le 2000000
∑ai≤2000000,另外,不保证集合中的数满足互异性,即有可能出现
a
i
=
a
j
a_i=a_j
ai=aj 且
i
i
i 不等于
j
j
j。
算法分析
观察到和最大是
2000000
2000000
2000000,考虑对于每个和计算它对答案的贡献,如果它被累加进答案的次数为奇数个那么就对答案有贡献,否则由于异或的性质抵消,同样是枚举每个数选或不选的 0/1 背包模型,由于我们只记录奇偶性,可以使用 bitset
压缩,同时用异或运算替代加法对
2
2
2 取模的运算。
代码实现
#include <cstdio>
#include <bitset>
std::bitset<(int)2e6+5> f;
int main() {
int n;scanf("%d",&n);f[0]=1;
for(int i=1;i<=n;++i) {
int a;scanf("%d",&a);
f^=f<<a;
}
int ans=0;
for(int i=1;i<=(int)2e6;++i) if(f[i]) ans^=i;
printf("%d\n",ans);
return 0;
}