3687: 简单题
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 861 Solved: 399
[Submit][Status][Discuss]
Description
小呆开始研究集合论了,他提出了关于一个数集四个问题:
1.子集的异或和的算术和。
2.子集的异或和的异或和。
3.子集的算术和的算术和。
4.子集的算术和的异或和。
目前为止,小呆已经解决了前三个问题,还剩下最后一个问题还没有解决,他决定把
这个问题交给你,未来的集训队队员来实现。
Input
第一行,一个整数n。
第二行,n个正整数,表示01,a2….,。
Output
一行,包含一个整数,表示所有子集和的异或和。
Sample Input
2
1 3
1 3
Sample Output
6
HINT
【样例解释】
6=1 异或 3 异或 (1+3)
【数据规模与约定】
ai >0,1<n<1000,∑ai≤2000000。
另外,不保证集合中的数满足互异性,即有可能出现Ai= Aj且i不等于J
/*
设f[i]表示i出现在算术和中的次数,那么对于a[j],有f[i]+=f[i-a[j]]。最后统计哪些数出现了奇数次即可。
*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define ll long long
#define inf 1000000000
using namespace std;
inline ll read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int ans,n,a[],b[],f[],bin[];
void getans(int x)
{
int tot=;
for(int i=;i<=x;i++)
tot+=b[i];
ans^=tot;
}
void dfs(int k,int last)
{
if(k==n)return;
for(int i=last+;i<=n;i++)
{
b[k+]=a[i];
getans(k+);
dfs(k+,i);
}
}
void solve1()
{ans=;dfs(,);printf("%d\n",ans);}
void solve2()
{
ans=;f[]=;
for(int i=;i<=n;i++)
for(int j=;j>=a[i];j--)
f[j]+=f[j-a[i]];
for(int i=;i<=;i++)
if(f[i]%)ans^=i;
printf("%d\n",ans);
}
int main()
{
bin[]=;for(int i=;i<=;i++)bin[i]=bin[i-]*;
n=read();
for(int i=;i<=n;i++)
a[i]=read();
if(n<=)solve1();
else solve2();
return ;
}
暴力 %%%黄学长
/*
这道题f[i]表示和为i的集合个数为奇数还是偶数,
f<<x表示f集合加上x后的集合,每次加入一个数,就用原集合异或一下这个集合就可以了。
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<bitset> using namespace std;
bitset<>f;
int n,m,x,ans; int main()
{
scanf("%d",&n);f[]=;
for(int i=;i<=n;i++)
{
scanf("%d",&x);
f^=(f<<x),m+=x;
cout<<f[i]<<endl;
}
for(int i=;i<=m;i++)
{
if(f[i]) ans^=i;
}
printf("%d\n",ans);
return ;
}