【jzoj4841】【平衡的子集】【搜索】
2016-11-09 11:44
190 查看
题目大意
夏令营有N个人,每个人的力气为M(i)。请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法?
解题思路
使用meet in the middle,分开暴力枚举将两个集合的差值求出来,保存选取情况,合并的时候hash判重。
code
#include<set> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define LL long long #define LD double #define mod(p) (p%size) #define max(a,b) ((a>b)?a:b) #define min(a,b) ((a>b)?b:a) #define fo(i,j,k) for(int i=j;i<=k;i++) #define fd(i,j,k) for(int i=j;i>=k;i--) using namespace std; int const inf=2147483647; int const maxn=20,maxm=1000007; int n,p,aa[maxn+10],h[maxm+20],s[maxm+20],two[maxn+10];LL size=1000007; struct rec{ int a,b; friend bool operator<(rec x,rec y){ return (x.a<y.a)||((x.a==y.a)&&(x.b<y.b)); } }; rec a[maxm+10],b[maxm+10]; /*inline LL mod(LL p){ return ((p>=size)?(p-size):p); }*/ int hash(LL pos){ p=mod(mod(mod(pos)+size)); for(;h[p]&&(h[p]!=pos);)p=mod(p)+1; return p; } int main(){ //freopen("subset.in","r",stdin); //freopen("subset.out","w",stdout); freopen("d.in","r",stdin); freopen("d.out","w",stdout); scanf("%d",&n); fo(i,1,n)scanf("%d",&aa[i]); int ans=0,maxs=1,tmp2,nn=(n+1)/2,ii,iii,tmp,p,cnta=0,cntb=0; fo(i,1,nn)maxs*=3; two[0]=1; fo(i,1,20)two[i]=two[i-1]*2; fo(i,0,maxs-1){ ii=i,tmp=0,tmp2=0; fo(j,1,nn){ iii=ii%3; ii/=3; if(iii==1)tmp+=aa[j]; else if(iii==2)tmp-=aa[j]; tmp2=tmp2+(iii!=0)*two[j]; } a[++cnta].a=tmp;a[cnta].b=tmp2; } sort(a+1,a+cnta+1); maxs=1; fo(i,1,n-nn)maxs*=3; fo(i,0,maxs-1){ ii=i,tmp=0,tmp2=0; fo(j,nn+1,n){ iii=ii%3; ii/=3; if(iii==1)tmp+=aa[j]; else if(iii==2)tmp-=aa[j]; tmp2=tmp2+(iii!=0)*two[j]; } b[++cntb].a=tmp;b[cntb].b=tmp2; } sort(b+1,b+cntb+1); int j=1,k; fo(i,1,cntb){ for(;(j<=cnta)&&(a[j].a<b[i].a);j++); k=j; for(;(k<=cnta)&&(a[k].a==b[i].a);k++){ p=hash(a[k].b+b[i].b); if(!h[p]){ h[p]=a[k].b+b[i].b; ans++; } } } printf("%d",ans-1); return 0; }
相关文章推荐
- 【JZOJ4841】【NOIP2016提高A组集训第4场11.1】平衡的子集
- 【JZOJ4841】平衡的子集
- AVLTree——平衡搜索树
- 搜索:平衡2-3-4树和(左倾)红黑树
- JZOJ 4841【NOIP2016提高A组集训第4场】平衡的子集
- 【数据结构】中的平衡搜索树-AVLTree
- 浅谈平衡搜索树之AVL树
- 通过有序数组生成平衡搜索二叉树
- 【NOIP2016提高A组集训第4场11.1】平衡的子集
- 【NOIP2016提高A组集训第4场11.1】平衡的子集
- AVL平衡搜索树
- 平衡搜索树—红黑树RBTree
- 平衡搜索树—AVLTree
- 高效的平衡搜索树——红黑树
- 平衡搜索树—AVLTree
- HDU 4085 Peach Blossom Spring 记忆化搜索枚举子集 斯坦纳树
- C++实现平衡搜索树
- 平衡搜索树-AVL树
- 平衡搜索树之红黑树(图片格式)
- 折半搜索+状态压缩【P3067】 [USACO12OPEN]平衡的奶牛群Balanced Cow S…