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. MongoDB学习笔记(四)

    第四章 Mongodb聚合函数 插入 测试数据 for(var j=1;j<3;j++){ for(var i=1;i<3;i++){ var person={ Name:"ja ...

  2. 简单的Java逻辑小代码(打擂台,冒泡排序,水仙花数,回文数,递归)

    1.打擂台 简单的小代码,打擂台.纪念下过去,祝福下新人. public static void main(String[] args){ int[] ld = {1,4,2,10,8,9,5}; i ...

  3. 重定向和servlet生命周期

    重定向(1)什么是重定向服务器通知浏览器向一个新的地址发送请求.注:可以发送一个302状态码和一个Location消息头.(该消息头包含了一个地址,称之为重定向地址),浏览器收到之后,会立即向重定向地 ...

  4. sso系统使用

    一:什么是sso(single sign on) ? sso(单点登录系统)简单说就是客户端第一次访问应用1的时候,由于没有登录,会被引导到登录页面进行登录,如果登录校验通过,将返回一个认证信息tic ...

  5. CXF 5参考资料

    下载 描述 名字 大小 下载方法 本教程示例应用程序的源代码 CXF_Spring_Survey_Src.war 10 KB HTTP 关于下载方法的信息 学习 Apache CXF 的官方站点:提供 ...

  6. 第8章-Java集合 --- 概述

    第8章-Java集合 --- 概述 (1)Java集合类是一种特别有用的工具类,可以用于存储数量不等的多个对象,并可以实现常用的数据结构,如 栈.队列等. (2)Java集合大致可分为Set.List ...

  7. MySQL数据库开发规范知识点

    前言: 设计规范更多的是为了确保数据库设计的合理性.为了项目最终的协调稳定性,而命名规范则更多的是为了确保设计的正式和统一. 约定优先于配置(Convention Over Configuration ...

  8. Scala编程入门---数组操作之数组转换

    使用yield和函数式编程转换数组 //对Array进行转换,获取的还是Aarry val a = Array(1,2,3,4,5) val a2 = for(ele <- a) yield e ...

  9. 在Ubuntu系统安装Sencha CMD

    Now type from the terminal prompt followed by Enter:   1 root@prompt:cd /java   1 root@prompt:tar zx ...

  10. DevOps之三 Git的安装与配置

    Centos7 安装Git 一.卸载Centos7 自带的git # git --version git version 1.8.3.1# whereis gitgit: /usr/bin/git / ...