嘟嘟嘟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;
}

最新文章

  1. RakNet基本教程
  2. HTTP狀態碼
  3. HDU4003Find Metal Mineral[树形DP 分组背包]
  4. Nodejs进阶:基于express+multer的文件上传
  5. swift语言的学习笔记
  6. 浅入DNS
  7. 获取表单的初始值,模拟placeholder属性
  8. Redis多机功能总结
  9. CSS3属性text-overflow(省略符)实战开发详解
  10. GitHub删除文件
  11. tomcat使用cookies缓存的时候中文报错解决办法 java.lang.IllegalArgumentException: Control character in cookie value or attribute.
  12. Hibernate根据实体类自动创建表
  13. Cookie的HttpOnly、secure、domain属性
  14. Python3 configparser值为多行时配置文件书写格式
  15. fold算法(拉格朗日插值)
  16. 关于Android file.createNewFile() 失败的问题
  17. virtualbox+vagrant学习-2(command cli)-25-Machine Readable Output
  18. 免密码登录服务器python脚本
  19. delete和truncate操作
  20. jave web 监听器。

热门文章

  1. Java学习--Cookie 和session
  2. 浏览器根对象window之操作方法
  3. Qt编译目录下exe文件执行报错问题的解决办法
  4. 润乾报表与DERBY数据库的创建连接详解
  5. the detailed annotation of StringBuilder
  6. 八、Vue中的computed属性
  7. MySQL 、SQL MS Access、和 SQL Server 数据类型
  8. 关于Entity Framework更新的几种方式以及可能遇到的问题(附加类型“Model”的实体失败,因为相同类型的其他实体已具有相同的主键值)在使用 &quot;Attach&quot; 方法或者将实体的状态设置为 &quot;Unchanged&quot; 或 &quot;Modified&quot; 时如果图形中的任何实体具有冲突键值,则可能会发生上述行为
  9. C# .Net动态调用webService
  10. iOS设计模式 - 代理