嘟嘟嘟




看数据范围,就能想到折半搜索。

但怎么搜,必须得想清楚了。

假设金币总数为1000,有20个人,首先搜前10个人,把答案记下来。然后如果在后十个人中搜到了4个人,价值为120,那么我们应该在记录的答案中的6个人中找价值最接近380的。

luogu的第一篇题解写的特别好,没有用set,而是以人数为第一关键字,价值为第二关键字排序。这样保证了同一人数的金币是单调的,就可以二分查找了。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cmath>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<cstdlib>
  7. #include<cctype>
  8. #include<vector>
  9. #include<stack>
  10. #include<queue>
  11. #include<set>
  12. using namespace std;
  13. #define enter puts("")
  14. #define space putchar(' ')
  15. #define Mem(a, x) memset(a, x, sizeof(a))
  16. #define In inline
  17. typedef long long ll;
  18. typedef double db;
  19. const ll INF = 1e18;
  20. const db eps = 1e-8;
  21. const int maxn = 35;
  22. inline ll read()
  23. {
  24. ll ans = 0;
  25. char ch = getchar(), last = ' ';
  26. while(!isdigit(ch)) last = ch, ch = getchar();
  27. while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
  28. if(last == '-') ans = -ans;
  29. return ans;
  30. }
  31. inline void write(ll x)
  32. {
  33. if(x < 0) x = -x, putchar('-');
  34. if(x >= 10) write(x / 10);
  35. putchar(x % 10 + '0');
  36. }
  37. int n, m, a[maxn];
  38. struct Node
  39. {
  40. int num; ll sum;
  41. In bool operator < (const Node& oth)const
  42. {
  43. return num < oth.num || (num == oth.num && sum < oth.sum);
  44. }
  45. }t[1 << (maxn >> 1)];
  46. ll tp[1 << (maxn >> 1)];
  47. int cnt = 0, l[maxn >> 1];
  48. ll Sum = 0, ans = INF;
  49. In void calc(int num, ll sum)
  50. {
  51. if(num < 0) return;
  52. int pos = lower_bound(tp + l[num], tp + l[num + 1], (Sum >> 1) - sum) - tp;
  53. if(pos < l[num + 1]) ans = min(ans, abs(Sum - ((sum + tp[pos]) << 1)));
  54. if(pos > l[num]) ans = min(ans, abs(Sum - ((sum + tp[pos - 1]) << 1)));
  55. }
  56. int main()
  57. {
  58. int T = read();
  59. while(T--)
  60. {
  61. ans = INF; cnt = 0; Sum = 0;
  62. n = read(); m = n >> 1;
  63. for(int i = 1; i <= n; ++i) a[i] = read(), Sum += a[i];
  64. for(int i = 0; i < (1 << m); ++i)
  65. {
  66. int num = 0; ll sum = 0;
  67. for(int j = 0; j < m; ++j)
  68. if((i >> j) & 1) ++num, sum += a[j + 1];
  69. t[++cnt] = (Node){num, sum};
  70. }
  71. sort(t + 1, t + cnt + 1);
  72. for(int i = 1; i <= cnt; ++i) tp[i] = t[i].sum;
  73. for(int i = 1; i <= cnt; ++i) if(t[i].num ^ t[i - 1].num) l[t[i].num] = i;
  74. l[m + 1] = cnt + 1;
  75. for(int i = 0; i < (1 << (n - m)); ++i)
  76. {
  77. int num = 0; ll sum = 0;
  78. for(int j = 0; j < n - m; ++j)
  79. if((i >> j) & 1) ++num, sum += a[j + m + 1];
  80. calc(m - num, sum);
  81. }
  82. write(ans), enter;
  83. }
  84. return 0;
  85. }

[TJOI2010]分金币的更多相关文章

  1. [luogu3878][TJOI2010]分金币【模拟退火】

    题目描述 现在有n枚金币,它们可能会有不同的价值,现在要把它们分成两部分,要求这两部分金币数目之差不超过1,问这样分成的两部分金币的价值之差最小是多少? 分析 根据模拟退火的基本套路,先随机分两堆金币 ...

  2. luogu P3878 [TJOI2010]分金币

    [返回模拟退火略解] 题目描述 今有 nnn 个数 {ai}\{a_i\}{ai​},把它们分成两堆{X},{Y}\{X\},\{Y\}{X},{Y},求一种分配使得∣∑i∈Xai−∑i∈Yai∣|\ ...

  3. [Luogu3878] [TJOI2010]分金币

    题目描述 现在有n枚金币,它们可能会有不同的价值,现在要把它们分成两部分,要求这两部分金币数目之差不超过1,问这样分成的两部分金币的价值之差最小是多少? 输入输出格式 输入格式: 每个输入文件中包含多 ...

  4. [洛谷P3878][TJOI2010]分金币

    题目大意:把$n(n\leqslant30)$个数分成两组,两组个数最多相差$1$,求出两组元素差的绝对值最小使多少 题解:模拟退火 卡点:$\exp$中的两个数相减写反,导致$\exp(x)$中的$ ...

  5. Luogu-3878 [TJOI2010]分金币

    这题和在我长郡考试时的一道题思路差不多...考虑折半搜索,预处理左半边选的方案所产生的数量差值\(x\)以及价值差值\(y\),把\(y\)扔到下标为\(x\)的set里面,然后在搜索右半边,每搜出一 ...

  6. 分金币 bzoj 3293

    分金币(1s 128M)  coin [问题描述] 圆桌上坐着n个人,每人有一定数量的金币,金币总数能被n整除.每个人可以给他左右相邻的人一些金币,最终使得每个人的金币数目相等.你的任务是求出被转手的 ...

  7. 【BZOJ-3293&1465&1045】分金币&糖果传递×2 中位数 + 乱搞

    3293: [Cqoi2011]分金币 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 854  Solved: 476[Submit][Status] ...

  8. 【贪心+中位数】【UVa 11300】 分金币

    (解方程建模+中位数求最短累积位移) 分金币(Spreading the Wealth, UVa 11300) 圆桌旁坐着n个人,每人有一定数量的金币,金币总数能被n整除.每个人可以给他左右相邻的人一 ...

  9. 【BZOJ3293】分金币(贪心)

    [BZOJ3293]分金币(贪心) 题面 BZOJ 洛谷 题解 和上一题一样啊. #include<cstdio> #include<cmath> #include<al ...

随机推荐

  1. Jmeter获取接口返回数组的长度

    添加BeanShell PostProcessor来获取,具体代码如下: import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath ...

  2. JAVA中ArrayList与LinkedList的区别以及对应List使用foreach与使用下标遍历的效率问题

    近期在做一个对接京东的电商平台,所以对各个地方的效率考虑的比较多,今天深挖了一下ArrayList与LinkedList的区别以及对应List使用foreach与使用下标遍历的效率问题,首先说一下两种 ...

  3. C++ QT中自定义控件的简单创建

    为了给控件添加自定义的方法以及重绘控件,我们需要自定义控件来达到自己希望的结果,网上的自定义控件文章比较少,并且过程比较粗略. 此教程以中文版的QT Creator进行介绍 首先我们创建一个新的项目, ...

  4. layui 文字滚动

    将消息标题滚动 上面是效果 <li class="layui-nav-item"> <div class="layui-carousel" i ...

  5. activeX

    对外接口和classid在idl文件中,接口功能实现在ctrl类中实现

  6. [Laravel] Laravel的基本数据库操作部分

    [laravel] laravel的数据库配置 找到程序目录结构下.env文件 配置基本的数据库连接信息 DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=blog ...

  7. Java并发编程:Java线程池核心ThreadPoolExecutor的使用和原理分析

    目录 引出线程池 Executor框架 ThreadPoolExecutor详解 构造函数 重要的变量 线程池执行流程 任务队列workQueue 任务拒绝策略 线程池的关闭 ThreadPoolEx ...

  8. quartz部署出现找不到表的情况,错误提示: Table 'heart_beat.QRTZ_LOCKS' doesn't exist

    描述一下,本地可以,部署到Linux就不行,Linux上的数据库是本地直接拷贝上去的,项目环境是Spring Boot2.1.Shiro.MyBatis.Redis.swagger.Bootstrap ...

  9. eclipse中安装windowbuilder插件、应用及卸载

    一.安装windowbuilder插件 1.找到对应版本的windowbuilder 连接地址:http://www.eclipse.org/windowbuilder/download.php 如图 ...

  10. http请求的headers详解

    关于http请求的headers详解:这里以HTTP1.1为例结合postman返回的信息 1.Server →nginx/1.15.8   A name for the server  这是post ...