Luogu-3878 [TJOI2010]分金币
这题和在我长郡考试时的一道题思路差不多...考虑折半搜索,预处理左半边选的方案所产生的数量差值\(x\)以及价值差值\(y\),把\(y\)扔到下标为\(x\)的set里面,然后在搜索右半边,每搜出一个状态,设他的数量差值为\(a\),价值差值\(b\),根据题意,要满足数量差值小于1,就要找左半边的状态来互补一下,很显然,如果\(n\)是偶数,数量差就一定是0,否则可以是正负1,所以要在\(set[-a]\)或\(set[-a-1],set[-a+1]\)里二分找一个数\(c\)使他加\(b\)最小,答案去绝对值最小值就好了。注意下标要统一加\(n\),防止出现负值。
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef set<int> ST;
const int maxn=1<<15;
int t,n,a[maxn],ans;
ST st[110];
void ycl(){
for(int i=0;i<=109;i++)
st[i].clear();
ans=0x7fffffff;
int m=n/2,lim=1<<m;
for(int i=0;i<lim;i++){
int cnt=0,tot=0;
for(int j=1,k=1;j<=m;j++,k<<=1)
if(k&i) cnt++,tot+=a[j];
else cnt--,tot-=a[j];
st[cnt+n].insert(tot);
}
}
int check(int x,int y){
int ans=0x7fffffff;
ST::iterator p=st[x].lower_bound(y);
ST::iterator q=st[x].upper_bound(y);
if(p!=st[x].end()) ans=min(ans,abs(*p-y));
if(q!=st[x].end()) ans=min(ans,abs(*q-y));
return ans;
}
void work(){
int l=n/2;
int m=n-l,lim=1<<m;
for(int i=0;i<lim;i++){
int cnt=0,tot=0;
for(int j=1,k=1;j<=m;j++,k<<=1)
if(k&i) cnt++,tot+=a[l+j];
else cnt--,tot-=a[l+j];
cnt=n-cnt;
if(n%2)
ans=min(ans,min(check(cnt-1,-tot),check(cnt+1,-tot)));
else
ans=min(ans,check(cnt,-tot));
}
}
int main(){
// freopen(".in","r",stdin);
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
ycl();
work();
printf("%d\n",ans);
}
return 0;
}
Luogu-3878 [TJOI2010]分金币的更多相关文章
- luogu P3878 [TJOI2010]分金币
[返回模拟退火略解] 题目描述 今有 nnn 个数 {ai}\{a_i\}{ai},把它们分成两堆{X},{Y}\{X\},\{Y\}{X},{Y},求一种分配使得∣∑i∈Xai−∑i∈Yai∣|\ ...
- [luogu3878][TJOI2010]分金币【模拟退火】
题目描述 现在有n枚金币,它们可能会有不同的价值,现在要把它们分成两部分,要求这两部分金币数目之差不超过1,问这样分成的两部分金币的价值之差最小是多少? 分析 根据模拟退火的基本套路,先随机分两堆金币 ...
- [TJOI2010]分金币
嘟嘟嘟 看数据范围,就能想到折半搜索. 但怎么搜,必须得想清楚了. 假设金币总数为1000,有20个人,首先搜前10个人,把答案记下来.然后如果在后十个人中搜到了4个人,价值为120,那么我们应该在记 ...
- [Luogu3878] [TJOI2010]分金币
题目描述 现在有n枚金币,它们可能会有不同的价值,现在要把它们分成两部分,要求这两部分金币数目之差不超过1,问这样分成的两部分金币的价值之差最小是多少? 输入输出格式 输入格式: 每个输入文件中包含多 ...
- [洛谷P3878][TJOI2010]分金币
题目大意:把$n(n\leqslant30)$个数分成两组,两组个数最多相差$1$,求出两组元素差的绝对值最小使多少 题解:模拟退火 卡点:$\exp$中的两个数相减写反,导致$\exp(x)$中的$ ...
- 分金币 bzoj 3293
分金币(1s 128M) coin [问题描述] 圆桌上坐着n个人,每人有一定数量的金币,金币总数能被n整除.每个人可以给他左右相邻的人一些金币,最终使得每个人的金币数目相等.你的任务是求出被转手的 ...
- 【BZOJ-3293&1465&1045】分金币&糖果传递×2 中位数 + 乱搞
3293: [Cqoi2011]分金币 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 854 Solved: 476[Submit][Status] ...
- 【贪心+中位数】【UVa 11300】 分金币
(解方程建模+中位数求最短累积位移) 分金币(Spreading the Wealth, UVa 11300) 圆桌旁坐着n个人,每人有一定数量的金币,金币总数能被n整除.每个人可以给他左右相邻的人一 ...
- 【BZOJ3293】分金币(贪心)
[BZOJ3293]分金币(贪心) 题面 BZOJ 洛谷 题解 和上一题一样啊. #include<cstdio> #include<cmath> #include<al ...
随机推荐
- JavaScript 变量,数据类型
这篇笔记呢,咱记录下变量和数据类型的基础知识,因为两者有联系 所以放在一起记录 1 如何声明变量 变量声明使用var关键字,下面举一些变量声明的例子: <!DOCTYPE html> &l ...
- 构造方法与构造块的执行顺序(区别于static)
小面试题:在类的实例化时,会调用类的构造块(类中的构造块)和构造方法,无论构造方法在前还是在后,都先执行构造块 class Person{ public Person(){ System.out.pr ...
- iOS 设置Label中特定的文字大小和颜色
直接上代码: _price = @"27"; NSMutableAttributedString *attributedString = [[NSMutableAttributed ...
- android实现卸载提示
这篇文章是整理的以前用过的一个功能,由于多种原因现在停用了,也希望这篇文章能帮助一些android入门的小童鞋.android是不提供监控卸载自己的功能的,这里使用了监控android日志的功能,an ...
- NPOI操作Excel常用函数
最近因项目接触了NPOI,感觉还是蛮不错的,网络上的教程普遍版本较老,本篇记录所常用操作,采用NPOI 2.0版本. 推荐: NPOI官方网站 NPOI 1.2.4/1.2.5 官方教程 新建Exce ...
- python——列表&字符串互相转换方法小结
字符串(str)转列表(list) 转换方法:str.split() str = 'zhu gao chao' print(str.split(' ')) # 用split进行转换 str——> ...
- Slyce,这家硅谷创业公司的来头你知道吗
Slyce,也许你没听过,一家硅谷创业公司,旨在帮助运动员和其他社会名流组织.优化社交媒体,过滤粉丝的声音,让明星更好的在社交媒体上和他们互动.但是如果如果说库里,那你应该就知道了,拿到了上届NBA总 ...
- python ipython notebook或者 jupyter notebook 的安装
IPython Notebook使用浏览器作为界面,向后台的IPython服务器发送请求,并显示结果.在浏览器的界面中使用单元(Cell)保存各种信息.Cell有多种类型,经常使用的有表示格式化文本的 ...
- 软件磁盘阵列(RAID)
RAID软件磁盘阵列 RAID 即廉价磁盘冗余阵列,其高可用性和可靠性适用于大规模环境中,相比正常使用,数据更需要被保护.RAID 是将多个磁盘整合的大磁盘,不仅具有存储功能,同时还有数据保护功能. ...
- linux环回文件
我们通常在设备上(比如磁盘分区)上创建文件系统,这些存储设备能够以设备文件的形式来使用,如/dev/device_name.为了使用存储设备上的文件系统,我们将其挂载到挂载点. 环回文件系统是指那些在 ...