CodeForce-752E

二分答案X,判断能否通过均分比X大的橘子,使得数量>=K。

对于给定x,均分A[i],能分得的种类数是

x * 2的t次方  <= A[i]  的最大的t

易知 

求得t后,所分得的权值差只有可能为1,即分得一堆Z和一堆Z+1

有时候虽然Z没有分的必要,但是Z+1还有继续分的必要,所以对于(Z+1) == 2 *X的情况,我们需要特殊考虑。

代码如下。

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
long long a[1000333];
long long e[40];
long long n, k;
bool check(long long x)
{
    long long cnt = 0;
    for (int i = 1 ; i <= n; i++)
    {
        //均分比X小的。
        if (a[i] < x) break;
        //求得分的次数
        int pos = upper_bound(e, e + 33, a[i] / x) - e - 1;
        cnt += e[pos];
        //如果分成e[pos]个正好变成e[pos]个X
        if (a[i] % e[pos] == 0) continue;
        //完全分成e[pos]份,部分还能继续分。
        if ((a[i] / e[pos] + 1) / x == 2 ) cnt += (a[i] % e[pos]);
    }
    if (cnt >= k) return true;
    else return false;
}
inline bool cmp(long long & x, long long & y)
{
    return x > y;
}
int main()
{

    cin >> n >> k;
    long long sum = 0;
    for (int i = 1; i <= n; i++)
    {
        scanf("%I64d", & a[i]);
        sum += a[i];
    }
    sort(a + 1, a + n + 1, cmp);
 
    if (sum < k)
    {
        cout << -1 << endl;
        return 0;
    }
    
    // 2 的 i 次方
    e[0] = 1;
    for (int i = 1 ; i <= 33; i++)
        e[i] = e[i - 1] * 2LL;
    
    long long ans = 1;
    long long l = 1, r = sum / k;
    
    //二分
    while (l <= r)
    {
        long long mid = (l + r) >> 1;
        if (check(mid))
        {
            ans = mid;
            l = mid + 1;
        }
        else
        {
            r = mid - 1;
        }
    }
    cout << ans << endl;
}
原文地址:https://www.cnblogs.com/HITLJR/p/6221000.html