话说为什么要嫉妒别人,太小心眼了吧。。。
简化题意!
有 $n$ 个小朋友,弹珠有 $m$ 个颜色,每个小朋友分到的弹珠都得是同一种颜色的,求分到弹珠最多的小朋友手里的弹珠数最少是多少?
进入正题!
这道题用$\color{red}{\text{二分}}$去解决会比较好。我默认为你已经看过题了。
为什么用$\color{red}{\text{二分}}$比较好?
- 此题具有单调性。什么意思?就是说小朋友分到的弹珠越多,嫉妒值越高;小朋友分到的弹珠越少,嫉妒值越低。
所以,我们可以先用二分模板去$\color{red}{\text{二分}}$小朋友的嫉妒值,然后每次对于 $mid$ 去调用 check
函数(check(mid)
)。那么,check
函数该怎么写呢?
- 很简单,我们用求每个颜色按每个小朋友 $mid$ 个弹珠,能分给多少个小朋友,用 $sum$ 记按每个每个小朋友 $mid$ 个弹珠最多能分给多少小朋友。若
sum>=n
,代表我们的嫉妒值得再大一些(小朋友的弹珠数量再大一些);否则,需要把嫉妒值调小。
展示代码!
#include <iostream>
using namespace std;
long long n,m,l=1,r,ans;
long long a[300010];
bool check(long long x){ //x 是当前的嫉妒值
long long sum=0;
for(int i=1;i<=m;i++) sum+=(a[i]+x-1)/x;
return sum<=n;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){cin>>a[i];r+=a[i];} //mid 的极限是总共的球数
while(l<r){ //二分模板
long long mid=(l+r)/2+1;
if(check(mid)){r=mid-1;ans=mid;}
else l=mid;
}
cout<<ans;
return 0;
}