【BZOJ】3687 简单题 DP+bitset

题目传送门

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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值