D - Project Planning
题意:
给定
n
n
n 种小球,每种小球
A
i
A_i
Ai 个。要求每
m
m
m 个互不相同的小球可以在一起放到一个盒子里,求最多可以放多少个盒子。
思路:
先说说二分的正确性
二分答案每次
c
h
e
c
k
check
check 的肯定是盒子数量
m
i
d
mid
mid,因为每个盒子不能出现重复的小球,因此每种小球至多取
m
i
n
(
m
i
d
,
A
i
)
min(mid,A_i)
min(mid,Ai) 个,取完
n
n
n 种小球的总数量为
s
u
m
sum
sum,而装成
m
i
d
mid
mid 个盒子至少需要
m
i
d
×
m
mid\times m
mid×m 个小球。
因此装成
m
i
d
mid
mid 个盒子只需满足
∑
i
=
1
n
m
i
n
(
m
i
d
,
A
i
)
>
=
m
i
d
×
m
\sum_{i=1}^n min(mid,A_i) >= mid \times m
∑i=1nmin(mid,Ai)>=mid×m 即可。
满足上述条件时,一个很显然的放置小球的方式即为,每次把该种小球的
x
x
x 个依次放入不同且数量未到达
m
m
m 的盒子中,二分正确性显然
二分
c
h
e
c
k
check
check 满足条件的最大值即可
code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define eps 1e-6
using namespace std;
const int maxn = 2e5 + 9;
const int mod = 1e9 + 7;
ll n, m;
ll a[maxn];
bool check(ll x){
ll c = 0;
for(int i = 1; i <= n; ++i) c += min(a[i], x);
return c >= x * m;
}
void work()
{
cin >> n >> m;
ll sum = 0;
for(int i = 1; i <= n; ++i) cin >> a[i], sum += a[i];
ll r = sum / m, l = 0;
while(l < r)
{
ll mid = (l + r + 1) >> 1;
if(check(mid)) l = mid;
else r = mid - 1;
}
cout << r;
}
int main()
{
ios::sync_with_stdio(0);
// int TT;cin>>TT;while(TT--)
work();
return 0;
}