P7585 [COCI2012-2013#1] LJUBOMORA

https://www.luogu.com.cn/problem/P7585
涉及知识点:二分
橙色题

 
思路:
这道题正解是二分,关键词为最大值(即嫉妒值)最小。看到这种问题的可优先考虑二分。确定核心算法后,进一步分析发现:如果每个分到弹珠的孩子都分到最多的弹珠,那么嫉妒值越大,分到弹珠的孩子越少;嫉妒值越小,分到弹珠的孩子越少。这个嫉妒值是具有单调性的,满足二分的要求。所以确定本题为二分答案。
check函数的思路:我们需要将相同颜色的弹珠尽量按当前枚举的数量平均分给小盆友们,具体的模拟过程就是除法。我们通过二分枚举嫉妒值 mid,发现第 i 种颜色的弹珠数 a_iai 至少需要分给 \left\lceil\dfrac{a_i}{mid}\right\rceilmidai⌉ 个孩子。最后把每种颜色的弹珠所分得的孩子数加起来就得到最小的孩子数了。

代码:
复制代码
#include<bits/stdc++.h> #define ll long long //这里意思是将long long缩写为ll,省点力气 using namespace std; const int N = 300000 + 10; ll n, m, l, r, ans, mid, a[N]; bool check(ll x){ ll sum = 0; for(int i=1;i<=m;i++){ sum += a[i] / x; if(a[i] % x != 0) sum++; //也有题解写成 sum+=(a[i]+x-1)/x,是等价的 } return sum <= n;//人数是否达标? } int main(){ cin >> n >> m; for(int i=1;i<=m;i++){ cin >> a[i]; r += a[i];//确定右边界,嫉妒值极限为所有球之和 } while(l <= r){//开始二分 mid = (l + r) >> 1;//等价于 /2 if(check(mid)){//返回true说明可以往左边找更大的嫉妒值,因为有的孩子可以得不到弹珠  r = mid - 1; ans = mid; }else l = mid + 1;//返回false说明人数太多,大于n,所以可以往右边找更大的嫉妒值  } cout << ans << endl;//输出答案 return 0; }
复制代码

 

 

 

__EOF__

本文作者灰の魔女伊蕾娜
本文链接https://www.cnblogs.com/2elaina/p/16460082.html
关于博主:编程小萌新一名,希望从今天开始慢慢提高,一步步走向技术的高峰!
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   -イレイナ  阅读(109)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示