P5815 CQOI2010 扑克牌
P5815 CQOI2010 扑克牌 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
首先 \(J\) 是个障眼法,稍微思考可知它和数字牌无区别。直接把 \(J\) 当作 \(0\) 号牌即可。也就是 \(n + 1\) 张牌中一次拿 \(n\) 张不同的牌。
容易想到这种拿法相当于,给某种牌添一张,然后在 \(n+1\) 种牌中每种牌都取一张。
又可发现答案具有单调性,二分答案,转化为判定性问题:是否可以拿 \(x\) 次?
拿 \(x\) 次可以分解为:先考虑添 \(x\) 次牌,然后取 \(x\) 次牌。显然等价于添 \(x\) 次牌使得每种牌的数量不少于 \(x\)。
计算一下把每种牌补到 \(x\) 张需要补的牌数是否超过 \(x\) 即可。
算一下二分右边界。答案最大显然应该是 \(n = 2\),\(m = c_1 =c_2 = 5 \times 10^8\) 的情况,算一下是 \(7.5 \times 10^8\)。这就是右边界了。
时间复杂度 \(\mathcal{O}(n\log c)\)。
\(n\) 的数据范围有点诈骗……
/*
 * @Author: crab-in-the-northeast 
 * @Date: 2022-10-21 10:53:06 
 * @Last Modified by: crab-in-the-northeast
 * @Last Modified time: 2022-10-21 10:59:48
 */
#include <bits/stdc++.h>
inline int read() {
    int x = 0;
    bool flag = true;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-')
            flag = false;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = (x << 1) + (x << 3) + ch - '0';
        ch = getchar();
    }
    if(flag)
        return x;
    return ~(x - 1);
}
const int maxn = 55;
int a[maxn];
int n;
inline bool check(int x) {
    long long t = 0;
    for (int i = 0; i <= n; ++i)
        if (x > a[i])
            t += x - a[i];
    
    return t <= x;
}
int main() {
    n = read();
    for (int i = 0; i <= n; ++i)
        a[i] = read();
    
    int ans = 0;
    
    for (int i = (1 << 30); i; i >>= 1)
        if (check(ans + i))
            ans += i;
    
    printf("%d\n", ans);
    return 0;
}

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号