1. 程式人生 > >【bzoj 3687 簡單題】【bitset的dp揹包優化】【bitset的妙用】

【bzoj 3687 簡單題】【bitset的dp揹包優化】【bitset的妙用】

【題意】

求n個數的所有子集的和的異或值

【分析】

    要求計運算元集算術和的異或和。首先我們設dp[i]表示由這n個數能有多少種方案組成i,顯然這樣dp[1~sum]就將所有的子集和統計完了,那麼計算的時候只要判斷(dp[i]&1)就有ans^=i。這樣的複雜度是sum*n,對於n=10^3,sum=2*10^6是處理不了的。那我們回過頭看看這個dp決策,假設前i個數組成的是dp',那麼在加入第i+1個數的時候每一個dp[j]+=dp[j-a[i+1]]]。而且我們可以將dp換成只有0/1,那麼dp[j]=(dp[j]+dp[j-a[i+1]])%2。即dp''=dp'^(dp'<<a[i+1])==>ans^=ans<<a[i+1],用bitset就行了。

【程式碼】

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 6;
int a[maxn];
bitset<maxn>b;

int main() {
	int n;
	scanf("%d", &n);
	int sum = 0;
	b[0] = 1;
	for (int i = 1; i <= n; i++) {
		int x;
		scanf("%d", &x);
		sum += x;
		b ^= b << x;
	}
	int ans = 0;
	for (int i = 1; i <= sum; i++) {
		if (b[i])ans++;
	}
	printf("%d\n", ans);
}