>传送门<
题意:给你一个有n个元素的数组,一个sum,让你找到数组的子集使得子集元素和等于sum,保证只有一个解决方案。

(其中1≤n≤36,0≤ sum<9*1018,0<ai<2*1017

思路:写这题的时候队友直接搜子集,然后我就满脸???236,老哥你确定不会爆?于是天真的我发现和背包不是很像么,然后就用背包写,写完后发现W是9*1018,此时我的内心对我自己也是???

所以暴搜肯定是不行的,有一个很巧妙的思路,就是将数组分成两个区域,18个元素我们完全可以暴力枚举子集,并放到set里,然后再对右区域枚举子集,O(1)检查sum - 子集和是否存在就行了,完美~

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
ll a[maxn];
set<ll> s;
map<ll, ll> mp; int main()
{
int n, p, q;
ll sum;
scanf("%d %lld", &n, &sum);
for(int i = 0; i < n; ++i) scanf("%lld", &a[i]);
p = n / 2; q = n - p;
//先枚举左区间
for(int i = 0; i < (1 << p); i++) {
ll tmp = 0;
for(int j = 0; j < p; j++) {
if(i & (1 << j))
tmp += a[j];
}
s.insert(tmp);
mp[tmp] = i; //记录状态
}
//枚举右区间
for(int i = 0; i < (1 << q); i++) {
ll ret = 0;
for(int j = 0; j < q; j++) {
if(i & (1 << j))
ret += a[p + j];
}
//找到答案了
if(s.find(sum - ret) != s.end()) {
ll x = mp[sum - ret];
for(int j = 0; j < p; ++j)
printf("%d", (bool)(x & (1 << j)));
for(int j = 0; j < q; ++j)
printf("%d", (bool)(i & (1 << j)));
printf("\n");
return 0;
}
}
return 0;
}

这题用到了这些知识点:子集的生成set的用法,map的用法

最新文章

  1. Ubuntu14.04下安装docker
  2. POI格式化Cell样式
  3. HDU 2717 Catch That Cow --- BFS
  4. dede 忘记密码在数据库中修改方法
  5. Maven构建Web项目问题汇总
  6. hdu 5340 (manacher)
  7. JavaScript基础精讲
  8. jmeter学习记录--05--Beanshell2
  9. pc端手機端自適應佈局方案
  10. python-虚拟环境搭建
  11. php-memcache基本用法
  12. emmc基础技术8:操作模式2-device identification mode
  13. Git:一本书 + 一个站点,让你掌握 Git
  14. mac os 里的 JAVA_HOME
  15. 中介者模式(QQ聊天室我觉得是个很生动的例子简单易懂)
  16. Windows10怎么架设局域网DNS服务器?
  17. 转:Sql Server中清空所有数据表中的记录
  18. LINUX 高可用群集之 ~Corosync~
  19. 读书笔记 Week6 2018-4-12
  20. HZAU 1205 Sequence Number(双指针)

热门文章

  1. 原生redis命令
  2. 超有用的linux笔记
  3. Centos7 密钥对登陆(适用于群晖DSM)
  4. Java 使用拦截器无限转发/重定向无限循环/重定向次数过多报错(StackOverflowError) 解决方案
  5. 最新最简洁Spring Cloud Oauth2.0 Jwt 的Security方式
  6. 请求接口获取的json 字符串 前后不能有 双引号
  7. 行业动态 | 利用Cassandra数据库揭开家族祖先的秘密
  8. 关于postgresql中numeric和decimal的精度和标度问题
  9. 如何用Python中自带的Pandas和NumPy库进行数据清洗
  10. 微服务网关1-Spring Cloud Gateway简介