平衡的子集 【NOIP2016提高A组集训第4场11.1】
2016-11-04 20:58
337 查看
Description
夏令营有N个人,每个人的力气为M(i)。请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法?Input
第一行一个整数N,表示人数。接下来N行,每行一个整数M(i)
Output
输出一行一个整数,表示一共多少种选法。Sample Input
41
2
3
4
Sample Output
3样例解释:
第一种选出{1,2,3},分成{1,2}和{3}两组;
第二种选出{1,3,4},分成{1,3}和{4}两组;
第三种选出{1,2,3,4},分成{1,4}和{2,3}两组。
Data Constraint
40%的数据满足:1<=M(i)<=1000;对于100%的数据满足:2<=N<=20,1<=M(i)<=100000000
剖解题目
。。。。解法
直接暴力是3^20,显然过不了。可以折半搜索。
每一个数只有选入第一集合,第二个集合或不选三种情况,分别用1,-1,0表示。
所以我们先3^10搜索前面的一半,记录所有状态。然后再搜索后面一半,看看是否有与前面状态一样的情况,记录答案。
当然,这有重复问题,我们用hash判重。
然而我人品太辣鸡,hash判重都被卡。。。。。。
可能是我连边问题。。。。
代码
#include<cstdio> #include<algorithm> #include<cstdlib> #include<cstring> #define fo(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=(1<<20)+5,mo=1079021; int a[25],ha[mo*2],fre[mo*2],next[mo*2],go[mo*2]; int n,num,ans; bool bz[maxn]; int hash(int x) { int y=x%mo+mo; while (ha[y]!=0&&ha[y]!=x) y=y%(mo*2)+1; if (!ha[y]) ha[y]=x; return y; } void add(int x,int y) { go[++num]=y; next[num]=fre[x]; fre[x]=num; } void dfs1(int now,int sum,int sta) { if (now>n/2) { int h=hash(sum); add(h,sta); return; } dfs1(now+1,sum,sta); dfs1(now+1,sum+a[now],sta+(1<<now-1)); dfs1(now+1,sum-a[now],sta+(1<<now-1)); } void dfs2(int now,int sum,int sta) { if (now>n){ int h=hash(sum); int i=fre[h]; while (i){ if (!bz[go[i]+sta]) bz[go[i]+sta]=true,++ans; i=next[i]; } return; } dfs2(now+1,sum,sta); dfs2(now+1,sum+a[now],sta+(1<<now-1)); dfs2(now+1,sum-a[now],sta+(1<<now-1)); } int main() { freopen("subset.in","r",stdin); freopen("subset.out","w",stdout); scanf("%d",&n); fo(i,1,n) scanf("%d",&a[i]); dfs1(1,0,0); dfs2(n/2+1,0,0); printf("%d",ans-1); }
相关文章推荐
- {题解}[jzoj4841]【NOIP2016提高A组集训第4场11.1】平衡的子集
- 【NOIP2016提高A组集训第4场11.1】平衡的子集
- 【NOIP2016提高A组集训第4场11.1】平衡的子集
- 【JZOJ4841】【NOIP2016提高A组集训第4场11.1】平衡的子集
- JZOJ 4841【NOIP2016提高A组集训第4场】平衡的子集
- NOIP2016提高A组集训第4场11.1 总结
- 【JZOJ4840】【NOIP2016提高A组集训第4场11.1】小W砍大树
- JZOJ 4840. 【NOIP2016提高A组集训第4场11.1】小W砍大树
- 【NOIP2016提高A组集训第7场11.4】推冰块
- 禅与园林艺术【NOIP2016提高A组集训第8场11.5】
- 【JZOJ4878】【NOIP2016提高A组集训第10场11.8】时空传送
- 三部曲 【NOIP2016提高A组集训第16场11.15】
- JZOJ4887. 【NOIP2016提高A组集训第13场11.11】最大匹配
- JZOJ4899. 【NOIP2016提高A组集训第17场11.16】雪之国度
- JZOJ 4823. 【NOIP2016提高A组集训第1场10.29】小W学物理
- JZOJ4822. 【NOIP2016提高A组集训第1场10.29】完美标号
- 【NOIP2016提高A组集训第1场10.29】小W学物理
- 【NOIP2016提高A组集训第14场11.12】随机游走——期望+树形DP
- 【JZOJ4845】【NOIP2016提高A组集训第5场11.2】寻找
- 高维宇宙 【NOIP2016提高A组集训第3场10.31】