BZOJ_2679_[Usaco2012 Open]Balanced Cow Subsets _meet in middle+双指针

Description

Farmer John's owns N cows (2 <= N <= 20), where cow i produces M(i) units of milk each day (1 <= M(i) <= 100,000,000). FJ wants to streamline the process of milking his cows every day, so he installs a brand new milking machine in his barn. Unfortunately, the machine turns out to be far too sensitive: it only works properly if the cows on the left side of the barn have the exact same total milk output as the cows on the right side of the barn! Let us call a subset of cows "balanced" if it can be partitioned into two groups having equal milk output. Since only a balanced subset of cows can make the milking machine work, FJ wonders how many subsets of his N cows are balanced. Please help him compute this quantity.

给出N(1≤N≤20)个数M(i) (1 <= M(i) <= 100,000,000),在其中选若干个数,如果这几个数可以分成两个和相等的集合,那么方案数加1。问总方案数。

Input

 Line 1: The integer N. 
 Lines 2..1+N: Line i+1 contains M(i).

Output

* Line 1: The number of balanced subsets of cows.

Sample Input

4 1 2 3 4
INPUT DETAILS: There are 4 cows, with milk outputs 1, 2, 3, and 4.

Sample Output

3


首先每个数的系数只可能是0,1,-1,并且1和-1都是选的状态。

用meet in middle的思想,$3^{n/2}$枚举左边和右边,把左边选或不选的状态与和挂链,右边按和排序。

枚举左边的状态,再枚举右边的和,枚举过程中左边指针单调。

然后统计答案即可。

复杂度$O(6^{n/2})$。

代码:

// luogu-judger-enable-o2
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define mr(x,y) make_pair(x,y)
#define N 100050
#define RR register
#define O2 __attribute__((optimize("-O2")))
typedef long long ll;
int n,a[25],m;
int ans;
int head[N],to[N],nxt[N],cnt,tot,t[N],vis[1<<22];
O2 struct A {
int v,S;
bool operator < (const A &x) const {
return v<x.v;
}
}b[N];
O2 inline void add(int u,int v) {
to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
}
O2 void dfs(int dep,int sum,int sta) {
if(dep==m+1) {
add(sta,sum); return ;
}
dfs(dep+1,sum,sta);
dfs(dep+1,sum+a[dep],sta|(1<<(dep-1)));
dfs(dep+1,sum-a[dep],sta|(1<<(dep-1)));
}
O2 void solve(int dep,int sum,int sta) {
if(dep==n+1) {
b[++tot].v=sum; b[tot].S=sta;
return ;
}
solve(dep+1,sum,sta);
solve(dep+1,sum+a[dep],sta|(1<<(dep-1)));
solve(dep+1,sum-a[dep],sta|(1<<(dep-1)));
}
O2 int main() {
scanf("%d",&n);
m=n/2;
RR int i,j;
for(i=1;i<=n;i++) scanf("%d",&a[i]);
dfs(1,0,0);
solve(m+1,0,0);
sort(b+1,b+tot+1);
for(i=0;i<(1<<m);i++) {
t[0]=0;
for(j=head[i];j;j=nxt[j]) {
t[++t[0]]=to[j];
}
sort(t+1,t+t[0]+1);
RR int l=1,r=1;
/*for(l=1;l<=t[0];l++) {
while(r<=tot&&b[r].v<t[l]) r++;
if(r==tot+1) break;
if(b[r].v==t[l]) {
vis[i|(b[r].S)]++;
//if(vis[i|b[r].S]==1) ans++;
}
}*/
for(l=1;l<=tot;l++) {
while(r<=t[0]&&t[r]<b[l].v) r++;
if(r==t[0]+1) break;
if(t[r]==b[l].v) {
vis[i|(b[l].S)]++;
if(vis[i|(b[l].S)]==1) ans++;
}
}
}
printf("%d\n",ans-1);
}

BZOJ_2679_[Usaco2012 Open]Balanced Cow Subsets _meet in middle+双指针的更多相关文章

  1. 【BZOJ 2679】[Usaco2012 Open]Balanced Cow Subsets(折半搜索+双指针)

    [Usaco2012 Open]Balanced Cow Subsets 题目描述 给出\(N(1≤N≤20)\)个数\(M(i) (1 <= M(i) <= 100,000,000)\) ...

  2. bzoj2679: [Usaco2012 Open]Balanced Cow Subsets(折半搜索)

    2679: [Usaco2012 Open]Balanced Cow Subsets Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 462  Solv ...

  3. 折半搜索+Hash表+状态压缩 | [Usaco2012 Open]Balanced Cow Subsets | BZOJ 2679 | Luogu SP11469

    题面:SP11469 SUBSET - Balanced Cow Subsets 题解: 对于任意一个数,它要么属于集合A,要么属于集合B,要么不选它.对应以上三种情况设置三个系数1.-1.0,于是将 ...

  4. [Usaco2012 Open]Balanced Cow Subsets

    Description Farmer John's owns N cows (2 <= N <= 20), where cow i produces M(i) units of milk ...

  5. BZOJ2679 : [Usaco2012 Open]Balanced Cow Subsets

    考虑折半搜索,每个数的系数只能是-1,0,1之中的一个,因此可以先通过$O(3^\frac{n}{2})$的搜索分别搜索出两边每个状态的和以及数字的选择情况. 然后将后一半的状态按照和排序,$O(2^ ...

  6. bzoj2679:[Usaco2012 Open]Balanced Cow Subsets

    思路:折半搜索,每个数的状态只有三种:不选.选入集合A.选入集合B,然后就暴搜出其中一半,插入hash表,然后再暴搜另一半,在hash表里查找就好了. #include<iostream> ...

  7. 【BZOJ】2679: [Usaco2012 Open]Balanced Cow Subsets

    [算法]折半搜索+数学计数 [题意]给定n个数(n<=20),定义一种方案为选择若干个数,这些数可以分成两个和相等的集合(不同划分方式算一种),求方案数(数字不同即方案不同). [题解] 考虑直 ...

  8. BZOJ.2679.Balanced Cow Subsets(meet in the middle)

    BZOJ 洛谷 \(Description\) 给定\(n\)个数\(A_i\).求它有多少个子集,满足能被划分为两个和相等的集合. \(n\leq 20,1\leq A_i\leq10^8\). \ ...

  9. SPOJ-SUBSET Balanced Cow Subsets

    嘟嘟嘟spoj 嘟嘟嘟vjudge 嘟嘟嘟luogu 这个数据范围都能想到是折半搜索. 但具体怎么搜呢? 还得扣着方程模型来想:我们把题中的两个相等的集合分别叫做左边和右边,令序列前一半中放到左边的数 ...

随机推荐

  1. 重写,string创建内存问题

     //重写equals方法,因为我们要对比的是date类中的时间而不是对象的引用地址 51     //如果传递的是Object类的话,我们就需要重写hashCode()方法,这样就比较麻烦,而且暂时 ...

  2. javaScript(7)---函数

    学习要点: 1.函数声明 2.return返回值 3.arguments对象 函数是定义一次但却可以调用或执行任意多次的一段JS代码.函数有时会有参数,即函数被调用时指定了值的局部变量.函数常常使用这 ...

  3. jquery中利用队列依次执行动画

    如果有5个隐藏的div,要让它们依次显示,通常的做法是要一个一个嵌套在回调函数里面,这样导致代码看起来非常不直观. $("#div1").slideDown(1000,functi ...

  4. JavaScript中两个对象数组 属性undefined

    var BaiduUsers = []; var UserArray = function(name, phone, id, id2) { this.name = name; this.phone = ...

  5. Linux下编译安装BOOST

    linux平台下要编译安装除gcc和gcc-c++之外,还需要两个开发库:bzip2-devel 和python-devel,因此在安装前应该先保证这两个库已经安装: #yum install gcc ...

  6. ubuntu11.04安装nginx+php+mysql

    先列参考内容,后面我再补充点东西: http://www.4wei.cn/archives/1001436 http://www.gidot.net/blog/article.asp?id=322 上 ...

  7. 【读英文文档】Whetting Your Appetite(刺激你的食欲)

    如果你有很多工作是通过计算机来完成的,那么你一定希望其中的很多事情能够自动地实现.比方说,你希望在文本文件中实现查找和替换的功能,以某一种机制实现照片的重命名以及重新排序的功能,一个小型的数据库甚至是 ...

  8. php定时执行操作及ob_flush()与flush()的使用

    版权声明:本文为博主原创文章,未经博主允许不得转载. http://blog.csdn.net/qq_38125058 一: 每隔30s执行一次,将字符串写入文件 // 30秒执行一次 ignore_ ...

  9. 杨老师课堂_VBA学习教程之根据部门列创建工作表

    课件下载 : 方式1:本节课件下载地址:链接: https://pan.baidu.com/s/1rf5pRmZ95fjVbz70KYi6Aw 密码: q9yk 方式2:或点击此处下载 效果预览图: ...

  10. js基础进阶--关于Array.prototype.slice.call(arguments) 的思考

    欢迎访问我的个人博客:http://www.xiaolongwu.cn Array.prototype.slice.call(arguments)的作用为:强制转化arguments为数组格式,一般出 ...