【BZOJ】3687 简单题 DP+bitset

来源:互联网 发布:2017网络用语及解释 编辑:程序博客网 时间:2024/06/12 04:43

题目传送门

前几天的考试考到了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;}