题目大意
你有$n$种牌,第$i$种牌的数目为$c_i$。另外有一种特殊的牌:joker,它的数目是$m$。你可以用每种牌各一张来组成一套牌,也可以用一张joker和除了某一种牌以外的其他牌各一张组成$1$套牌。比如,当$n=3$时,一共有$4$种合法的套牌:$\lbrace1,2,3\rbrace,\lbrace J,2,3\rbrace,\lbrace1,J,3\rbrace,\lbrace1,2,J\rbrace$。
给出$n,m$和$c_i$,你的任务是组成尽量多的套牌。每张牌最多只能用在一副套牌里(可以有牌不使用)。
题目分析
二分答案,然后扫描一遍检查一下是否合法。
实际上这道题并不好找到二分这个突破点。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include<algorithm> #include<iostream> #include<iomanip> #include<cstring> #include<cstdlib> #include<vector> #include<cstdio> #include<cmath> #include<queue> using namespace std; typedef long long LL; inline const LL Get_Int() { LL num=0,bj=1; char x=getchar(); while(x<'0'||x>'9') { if(x=='-')bj=-1; x=getchar(); } while(x>='0'&&x<='9') { num=num*10+x-'0'; x=getchar(); } return num*bj; } const int maxn=55; int n,m; LL a[maxn]; bool Check(int Limit) { LL sum=0; for(int i=1; i<=n; i++) if(Limit>a[i])sum+=Limit-a[i]; return sum<=min(m,Limit); } int main() { n=Get_Int(); m=Get_Int(); for(int i=1; i<=n; i++)a[i]=Get_Int(); int Left=0,Right=1e9; while(Left<=Right) { int mid=(Left+Right)>>1; if(Check(mid))Left=mid+1; else Right=mid-1; } printf("%d\n",Right); return 0; }
|