【bzoj3687】简单题

#3687. 简单题

内存限制:512 MiB时间限制:10 Sec

题目描述

小呆开始研究集合论了,他提出了关于一个数集四个问题:
1.子集的异或和的算术和。
2.子集的异或和的异或和。
3.子集的算术和的算术和。
4.子集的算术和的异或和。
    目前为止,小呆已经解决了前三个问题,还剩下最后一个问题还没有解决,他决定把
这个问题交给你,未来的集训队队员来实现。

输入格式

第一行,一个整数n。
第二行,n个正整数,表示01,a2….,。

输出格式

一行,包含一个整数,表示所有子集和的异或和。

样例

样例输入

2
1 3

样例输出

6

数据范围与提示

 

【样例解释】

  6=1 异或 3 异或 (1+3)

【数据规模与约定】

ai >0,1<n<1000,∑ai≤2000000。

另外,不保证集合中的数满足互异性,即有可能出现Ai= Aj且i不等于J

 

题解:

        自己异或两次的话就没有了。。。。。

        异或背包 , bitset优化一下;

        复杂度:  $O(\frac{n \sum a_{i} } {64} $

       反正bitset的复杂度比较玄学吧。。。。。。。。

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<queue>
 6 #include<cmath>
 7 #include<vector>
 8 #include<stack>
 9 #include<map>
10 #include<set>
11 #include<bitset>
12 #define Run(i,l,r) for(int i=l;i<=r;i++)
13 #define Don(i,l,r) for(int i=l;i>=r;i--)
14 #define ll long long
15 #define ld long double
16 #define inf 0x3f3f3f3f
17 using namespace std;
18 int n;
19 bitset<2000100>f;
20 int main(){
21     freopen("in.in","r",stdin);
22     freopen("out.out","w",stdout);
23     scanf("%d",&n);
24     int x , sum=0;
25     //f.reset();
26     f[0]=1;
27     Run(i,1,n){
28         scanf("%d",&x);
29         f^=f<<x;
30         sum += x;
31     }
32     int ans=0;
33     Run(i,1,sum){
34         if(f[i])ans^=i;
35     }
36     cout<<ans<<endl;
37     return 0;
38 }//by tkys_Austin;
View Code

 

posted @ 2018-11-03 20:23  大米饼  阅读(287)  评论(0编辑  收藏  举报