题目传送门
前几天的考试考到了bitset,于是我就去学了一发。
大佬传送门,这位大佬已经讲的很清楚了,我就不再赘述bitset的功能和用法了。
其实说白了,bitset就是一个可以位运算的bool数组罢了。
回到这题,我们可以很容易想到的是DP,定义f[i[表示当前子集的算术和为i的子集构成方案数。
状态转移方程也非常好想,f[j]+=f[j-a[i]]
然后就是统计答案,若f[i]&1>0,则ans^=i。
这题真的这么简单吗?难道出题人变得有良心了?孩子,别做梦了。
观察上面的状态转移方程和答案统计,我们可以发现最后的答案统计只和f[i]的奇偶性有关,于是我们可以把转移方程变成f[j]^=f[j-a[i]]
然后,根据异或的性质,我们又可以把方程转化成f[j]^=f[j-a[i]]<<a[i] -> ans^=ans<<a[i](至于为什么,我也不知道……)
然后问题就变得很简单了,只要O(n)扫一遍,边读入边统计答案,最后统计答案时再扫一遍就好了。
附上AC代码:
#include <cstdio>
#include <bitset>
using namespace std;
bitset <2000010> a;
int n,x,sum,ans;
int main(void){
scanf("%d",&n),a.set(0);
for (int i=1; i<=n; ++i) scanf("%d",&x),sum+=x,a^=a<<x;
for (int i=1; i<=sum; ++i) if (a[i]) ans^=i;
printf("%d",ans);
return 0;
}