题解 | #[CQOI2010]扑克牌#

[CQOI2010]扑克牌

https://ac.nowcoder.com/acm/problem/19916

  • 题目考点:二分 + 验证答案
  • 题目内容:给n种牌和一种Joker牌,问能合成几套牌,其中每一套牌要包含n种不同的牌(其中给定的n种牌中若有一种不够用,可以用Joker代替,Joker也只能在一套牌里出现一次)。
  • 题目分析:二分答案,例如题目样例:
3 4
1 2 3
//即第一种牌1张,第二种2张,第三种三张,joker 4 张,每套牌3张,至少含三种不同的牌

我们来模拟验证答案为2、3、4时的答案:
图片说明
观察到以下情形:
1、如图①和②,当第一种牌或者第二种牌不够用时,可以用joker替换;
2、如图①和②,使用的joker小于4,说明够用,则ans = 2 或 ans = 3能够组成 ;
3、如图③,当使用的joker大于m = 4,则说明joker不够用,不能组成;
4、如图③,当使用的joker大于ans = 4,则说明joker在不止一组中出现过,不符合题意。
因此代码如下:

#include<iostream>
#include<algorithm>

using namespace std;
typedef long long LL;

const int N = 55;
int a[N];
int n, m;

bool jud(int mid)
{
    LL ans = 0; //ans记得开logn long,有10分卡数据范围
    for(int i = 1; i <= n; i++)
        if(a[i] < mid) ans += mid - a[i];  //对应情形1
    //cout<<' '<<ans << ' '<< (ans <= m && ans <= mid)<<'\n';
    return ans <= m && ans <= mid; //对应情形2、3、4
}

int main()
{
    scanf("%d%d", &n, &m);
    int maxx = 0;
    for(int i = 1; i <= n; i++)
        scanf("%d", &a[i]), maxx = max(maxx, a[i]);

    int l = 1, r = maxx * 2;
    while(l < r)
    {
        int mid = l + r + 1 >> 1; //二分l = mid需要给和+1
        //cout<<mid <<' '<<l <<' '<< r;
        if(jud(mid)) l = mid;
        else r = mid - 1;
    }
    cout<< l;
    return 0;
}
题解专栏 文章被收录于专栏

希望不断进步

全部评论

相关推荐

09-19 13:59
门头沟学院 Java
用微笑面对困难:Trae一下,如果真成了,他用了直接发字节起诉代码版权,,这个代码不商用是没问题的如果没成也是情理之中的。
点赞 评论 收藏
分享
08-21 16:35
已编辑
门头沟学院 Java
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务