其他分享
首页 > 其他分享> > P7585 [COCI2012-2013#1] LJUBOMORA

P7585 [COCI2012-2013#1] LJUBOMORA

作者:互联网

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

 

 

 

标签:二分,弹珠,ll,嫉妒,mid,long,COCI2012,LJUBOMORA,P7585
来源: https://www.cnblogs.com/2elaina/p/16460082.html