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

时间:2023-02-18 09:47:30

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】&lbrack;Usaco2012 Open&rsqb;Balanced Cow Subsets(折半搜索&plus;双指针)

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

  2. bzoj2679&colon; &lbrack;Usaco2012 Open&rsqb;Balanced Cow Subsets&lpar;折半搜索&rpar;

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

  3. 折半搜索&plus;Hash表&plus;状态压缩 &vert; &lbrack;Usaco2012 Open&rsqb;Balanced Cow Subsets &vert; BZOJ 2679 &vert; Luogu SP11469

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

  4. &lbrack;Usaco2012 Open&rsqb;Balanced Cow Subsets

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

  5. BZOJ2679 &colon; &lbrack;Usaco2012 Open&rsqb;Balanced Cow Subsets

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

  6. bzoj2679:&lbrack;Usaco2012 Open&rsqb;Balanced Cow Subsets

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

  7. 【BZOJ】2679&colon; &lbrack;Usaco2012 Open&rsqb;Balanced Cow Subsets

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

  8. BZOJ&period;2679&period;Balanced Cow Subsets&lpar;meet in the middle&rpar;

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

  9. SPOJ-SUBSET Balanced Cow Subsets

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

随机推荐

  1. php解决中文截取乱码问题

    针对截取字符串出现中文乱码问题,网上有很多介绍,也有很多函数,但笔者看着网上的函数,总感觉有点别扭, 所以自己动手写了一个防止截取字符串时出现中文乱码的函数. 实现的原理还是比较简单,主要是利用ASC ...

  2. IntelliJ IDEA Community Edition 14&period;1&period;4下使用 Apache-Subversion搭建代码管理环境

    当前我的idea 版本是14.1.4. 1,)SVN Server下载与安装(https://www.visualsvn.com/server/): 因为我开发机是x64的,所以我优先下载 x64的 ...

  3. shell应用——主控脚本实现(1)

    shell脚本作用:内网ip,公网ip :cpu负载,内存使用量:ngix和mysql...

  4. 今天考试的JAVA编程题

    今天早上考了java, 题目感觉还不错, 共四道题,有一道定义类的没啥意思就没列出来. 这三道题目还是不错的,特别是第一道,大一上学期学linux的时候,那时还没学C语言呢,准确的来说,还不知道什么是 ...

  5. POJ2248 A Knight&&num;39&semi;s Journey&lpar;DFS&rpar;

    题目链接. 题目大意: 给定一个矩阵,马的初始位置在(0,0),要求给出一个方案,使马走遍所有的点. 列为数字,行为字母,搜索按字典序. 分析: 用 vis[x][y] 标记是否已经访问.因为要搜索所 ...

  6. js自定义事件、DOM&sol;伪DOM自定义事件

    一.说明.引言 我JS还是比较薄弱的,本文的内容属于边学边想边折腾的碎碎念,可能没什么条理,可能有表述不准确的地方,可能内容比较拗口生僻.如果您时间紧迫,或者JS造诣已深,至此您就可以点击右侧广告(木 ...

  7. 相对路径与绝对路径构造file对象

    package file; import java.io.File; public class FileTest1 { public static void main(String[] args) { ...

  8. 安装dotnet core

    CentOS 7.1下安装dotnet core .NET CORE的官方(http://dotnet.github.io/getting-started/)只提供了Windows, Ubuntu14 ...

  9. Visual Studio Team Services使用教程--邀请团队成员

  10. BZOJ 1171&colon; 大sz的游戏

    ZJOI讲课的题目,数据结构什么的还是很友好的说 首先我们发现题目中提到的距离\(\le L\)的东西显然可以用单调队列维护 但是暴力搞去不掉区间并的限制,那么我们考虑从区间并入手 对于这种问题的套路 ...