zoukankan      html  css  js  c++  java
  • bzoj1816 扑克牌

    Description

    你有n种牌,第i种牌的数目为ci。另外有一种特殊的牌:joker,它的数目是m。你可以用每种牌各一张来组成一套牌,也可以用一张joker和除了某一种牌以外的其他牌各一张组成1套牌。比如,当n=3时,一共有4种合法的套牌:{1,2,3}, {J,2,3}, {1,J,3}, {1,2,J}。 给出n, m和ci,你的任务是组成尽量多的套牌。每张牌最多只能用在一副套牌里(可以有牌不使用)。

    Input

    第一行包含两个整数n, m,即牌的种数和joker的个数。第二行包含n个整数ci,即每种牌的张数。

    Output

    输出仅一个整数,即最多组成的套牌数目。

    Sample Input

    3 4
    1 2 3

    Sample Output

    3

    样例解释
    输入数据表明:一共有1个1,2个2,3个3,4个joker。最多可以组成三副套牌:{1,J,3}, {J,2,3}, {J,2,3},joker还剩一个,其余牌全部用完。

    数据范围
    50%的数据满足:2 < = n < = 5, 0 < = m < = 10^ 6, 0< = ci < = 200
    100%的数据满足:2 < = n < = 50, 0 < = m, ci < = 500,000,000。
     
    二分,检验答案,注意joker的数量满足要求
    确定一个组数,每种不够的肯定要用joker来补,如果joker的数量超过了组的数量,那肯定是不行的,因为一组最多一张,如果没有超出数量,那么任意一种牌,在不需要他的时候可以用joker替代,需要他的时候肯定有剩余,因为joker代替其他牌时候对他的需求肯定比他的牌数要少,这样就确保joker数量满足时成立的充要条件
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int maxn = 105;
    int n,m,s,c[maxn];
    void input(){
        cin>>n>>m;
        s = 0;
        for(int i = 1;i <= n;i++){
            scanf("%d",&c[i]);
            if(s < c[i]) s = c[i];
        }
        s += m;
    }
    bool check(int t){
        int add = 0;
        for(int i = 1;i <= n;i++){
            if(t - c[i] > 0) add += t - c[i];
            if(t < add || m < add) return false;
        }
        return true;
    }
    void div(){
        int lans = 0,rans = s,mans;
        while(lans <= rans){
            mans = (lans + rans) >> 1;
            if(check(mans)){
                lans = mans + 1;
            }else{
                rans = mans - 1;
            }
        }
        if(check(mans))cout<<mans;
        else cout<<mans-1;
    }
    int main(){
        input();
        div();
        return 0;
    }
    View Code

    还有一种做法,在保证joker数量满足的情况下,确保前面的需求不大于当前牌的数量就可以,如果前面的需求后面能满足,那么后面的需求前面就一定能满足

    证明:

    假设当前判定牌的种类的数量为j,补充此类牌后,不满足要求的牌类为i,j之前的牌的需求,牌组数t

    j满足要求,即有j >= add

    有add + (t - j) - (t - i)> i

    add - j + i > i

    j < add

    与“j满足要求”的前提矛盾,等证前文的结论成立 

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int maxn = 105;
    int n,m,s,c[maxn];
    void input(){
        cin>>n>>m;
        s = 0;
        for(int i = 1;i <= n;i++){
            scanf("%d",&c[i]);
            if(s < c[i]) s = c[i];
        }
        s += m;
    }
    bool check(int t){
        int add = t - c[1];
        if(add < 0) add = 0;
        for(int i = 2;i <= n;i++){
            if(c[i] < add || m < add) return false;
            else{
                if(t - c[i] > 0) add += t - c[i];
            }
        }
        if(m < add) return false;
        return true;
    }
    void div(){
        int lans = 0,rans = s,mans;
        while(lans <= rans){
            mans = (lans + rans) >> 1;
            if(check(mans)){
                lans = mans + 1;
            }else{
                rans = mans - 1;
            }
        }
        if(check(mans))cout<<mans;
        else cout<<mans-1;
    }
    int main(){
        input();
        div();
        return 0;
    }
    View Code
  • 相关阅读:
    User Get 'Access Denied' with Excel Service WebPart
    How To Search and Restore files from Site Collection Recycle Bin
    How To Collect ULS Log from SharePoint Farm
    How To Restart timer service on all servers in farm
    How to Operate SharePoint User Alerts with PowerShell
    How to get Timer Job History
    Synchronization Service Manager
    SharePoint 2007 Full Text Searching PowerShell and CS file content with SharePoint Search
    0x80040E14 Caused by Max Url Length bug
    SharePoint 2007 User Re-created in AD with new SID issue on MySite
  • 原文地址:https://www.cnblogs.com/hyfer/p/5655820.html
Copyright © 2011-2022 走看看