SPOJ-SUBSET Balanced Cow Subsets
嘟嘟嘟spoj
嘟嘟嘟vjudge
嘟嘟嘟luogu
这个数据范围都能想到是折半搜索。
但具体怎么搜呢?
还得扣着方程模型来想:我们把题中的两个相等的集合分别叫做左边和右边,令序列前一半中放到左边的数为\(a\),右边的数为\(b\),后一半同理为\(c\)和\(d\)。则我们要找的就是满足\(a + c = b + d\)的选取方案。
然后变形\(a - b = d - c\)。因此我们只要在前一半枚举\(a, b\),存起来,然后在后一半枚举\(c, d\),然后查找\(d - c\)是否出现过。
注意不是每一个数都要选,所以枚举的时候有三种情况:1.不选。2.选到左边。3.选到右边。所以复杂度为\(O(3 ^ {\frac{n}{2}})\)。
还有一点就是状态判重,这个用二进制表示就行。
具体实现就是用\(map\)离散化\(a - b\),然后因为\(a - b\)可能由好多种选取方案得来的,所以开一个\(vector\)记录每一个\(a - b\)对应的状态。统计答案的时候用一个\(bool\)数组判重即可。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
#include<map>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define rg register
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 22;
const int maxp = 1.2e6 + 5;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
int n, m;
ll a[maxn];
int cnt = 0;
map<int, int> mp;
vector<int> v[maxp];
bool vis[maxp];
void dfs1(int stp, ll tot, int now)
{
if(stp > m)
{
if(mp.find(tot) == mp.end()) mp[tot] = ++cnt;
v[mp[tot]].push_back(now); return;
}
dfs1(stp + 1, tot, now);
dfs1(stp + 1, tot + a[stp], now + (1 << (stp - 1)));
dfs1(stp + 1, tot - a[stp], now + (1 << (stp - 1)));
}
void dfs2(int stp, ll tot, int now)
{
if(stp > n)
{
if(mp.find(tot) == mp.end()) return;
int id = mp[tot];
for(int i = 0; i < (int)v[id].size(); ++i) vis[v[id][i] | now] = 1;
return;
}
dfs2(stp + 1, tot, now);
dfs2(stp + 1, tot + a[stp], now + (1 << (stp - 1)));
dfs2(stp + 1, tot - a[stp], now + (1 << (stp - 1)));
}
int main()
{
n = read(); m = n >> 1;
for(int i = 1; i <= n; ++i) a[i] = read();
dfs1(1, 0, 0); dfs2(m + 1, 0, 0);
int ans = 0;
for(int i = 1; i < maxp; ++i) ans += (int)vis[i];
write(ans), enter;
return 0;
}
SPOJ-SUBSET Balanced Cow Subsets的更多相关文章
- 折半搜索+Hash表+状态压缩 | [Usaco2012 Open]Balanced Cow Subsets | BZOJ 2679 | Luogu SP11469
题面:SP11469 SUBSET - Balanced Cow Subsets 题解: 对于任意一个数,它要么属于集合A,要么属于集合B,要么不选它.对应以上三种情况设置三个系数1.-1.0,于是将 ...
- BZOJ_2679_[Usaco2012 Open]Balanced Cow Subsets _meet in middle+双指针
BZOJ_2679_[Usaco2012 Open]Balanced Cow Subsets _meet in middle+双指针 Description Farmer John's owns N ...
- bzoj2679: [Usaco2012 Open]Balanced Cow Subsets(折半搜索)
2679: [Usaco2012 Open]Balanced Cow Subsets Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 462 Solv ...
- 【BZOJ 2679】[Usaco2012 Open]Balanced Cow Subsets(折半搜索+双指针)
[Usaco2012 Open]Balanced Cow Subsets 题目描述 给出\(N(1≤N≤20)\)个数\(M(i) (1 <= M(i) <= 100,000,000)\) ...
- [Usaco2012 Open]Balanced Cow Subsets
Description Farmer John's owns N cows (2 <= N <= 20), where cow i produces M(i) units of milk ...
- BZOJ.2679.Balanced Cow Subsets(meet in the middle)
BZOJ 洛谷 \(Description\) 给定\(n\)个数\(A_i\).求它有多少个子集,满足能被划分为两个和相等的集合. \(n\leq 20,1\leq A_i\leq10^8\). \ ...
- BZOJ2679 : [Usaco2012 Open]Balanced Cow Subsets
考虑折半搜索,每个数的系数只能是-1,0,1之中的一个,因此可以先通过$O(3^\frac{n}{2})$的搜索分别搜索出两边每个状态的和以及数字的选择情况. 然后将后一半的状态按照和排序,$O(2^ ...
- bzoj2679:[Usaco2012 Open]Balanced Cow Subsets
思路:折半搜索,每个数的状态只有三种:不选.选入集合A.选入集合B,然后就暴搜出其中一半,插入hash表,然后再暴搜另一半,在hash表里查找就好了. #include<iostream> ...
- 【BZOJ】2679: [Usaco2012 Open]Balanced Cow Subsets
[算法]折半搜索+数学计数 [题意]给定n个数(n<=20),定义一种方案为选择若干个数,这些数可以分成两个和相等的集合(不同划分方式算一种),求方案数(数字不同即方案不同). [题解] 考虑直 ...
随机推荐
- Hibernate中查询优化策略
Hibernate查询优化策略 ² 使用延迟加载等方式避免加载多余数据 ² 通过使用连接查询,配置二级缓存.查询缓存等方式减少select语句数目 ² 结合缓存机制,使用iterate()方法减少查询 ...
- python 软件管理规范
一.背景 软件开发是一个系统工程,当然编码实现是其中尤其重要的一个环节,关乎到功能需求的实现好坏.这个环节中除了编码这一硬功之外,与之相关的编码风格这一柔道,虽然没有直接决定功能的实现与否,但却在很大 ...
- Quiver快速入门
Quiver快速入门 装载自:https://github.com/HappenApps/Quiver/wiki/Quiver%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8 ...
- 14:求10000以内n的阶乘
14:求10000以内n的阶乘 查看 提交 统计 提问 总时间限制: 5000ms 内存限制: 655360kB 描述 求10000以内n的阶乘. 输入 只有一行输入,整数n(0<=n< ...
- NTP POOL PROJECT:全球最大的免费NTP服务集群
pool.ntp.org项目是一个提供可靠易用的NTP服务的虚拟集群,它作为一个大的NP服务器可以支撑全球数百万客户端使用.该项目允许那些能提供NTP服务的服务器加入到该集群中,截止2012年8月份, ...
- 推荐一个 JavaScript 日期处理类库 Moment.js
官网: http://momentjs.com/ 处理时间的展示,很方便. 安装 bower install moment --save # bower npm install moment --sa ...
- mac os idea的快捷键
全局搜索:shift+command+f 搜索类:command+o 光标向前向后移动:command+option+(左/右) 删除一行: command+delete
- 快速 图片颜色转换迁移 Color Transfer Opencv + Python
Super fast color transfer between images About a month ago, I spent a morning down at the beach, w ...
- Android开发时,那些相见恨晚的工具或网站!
本文来我在知乎话题Android开发时你遇到过什么相见恨晚的工具或网站?下的回答! 在实际Android开发过程确实会有很多相见恨晚的工具或网站出现,下面是我自己的一些分享. 1.源码网站 https ...
- 【java8】为java8的foreach正名
首先为自己没有经过严格测试得出的错误结论感到抱歉,原博文,测试完感觉自己发现了一个新bug,后来思前想后觉得不应该是这样的,如果效率差的这么多,jdk的开发人员会不去优化它吗,但是怎么重复测试任然得到 ...