题解:B4427 [CSP-X2025 山东] 能量水晶
小学组居然出绿,果然比入门组难。
题目中要求最小值最大,乍一眼看上去像二分答案状物,但很快容易被假。
当一个存储罐存的过多导致无法分配满时,会导致最终答案出现 \(0\),答案变小,所以不是答案单调递增的。
此时我们审视数据范围,发现 \(a_i\) 极小,而每个储存罐最多分配 \(\max _ {i = 1} ^ n a_i\) 个水晶,所以我们只需从 \(1\) 到 \(n\) 模拟,记录下填满罐子数量和余下水晶的数量。
code:
for(int j = 1; j <= n; j++){
b[j] = a[j] % i;
cnt += a[j] / i;
}
接下来分为三种情况:
-
\(cnt \ge m\)
此时已经把 \(m\) 个罐子填满,因为每个罐子容量相同,所以我们只需输出 \(k \times i\)。
-
\(cnt \le m - k\)
此时我们发现无法填满罐子,所以前 \(k\) 小的罐子必定为 \(0\),答案为 \(0\)。
-
\(m - k < cnt < m\)
这种情况是最难搞的,此时会有 \(n - (m - k)\) 个满的,剩余的罐子就需要把上面存储的剩余水晶排序,选最大的前 \(n - m + cnt - 1\) 项。
code:
int sum = (cnt - m + k) * i; sort(b + 1, b + n + 1); for(int j = n; j > n - m + cnt; j--) sum += b[j]; ans = max(ans, sum);如果感觉比较抽象的话这里给一个图:

code:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<climits>
#include<bitset>
#define ll long long
#define ull unsigned long long
#define endl '\n'
#define y1 Y1
#define pii pair<int,int>
#define mkp make_pair
#define debug(x, y) cout << x << " " << y << endl
using namespace std;
inline int read(){
int t = 0, flag = 1;
char a = getchar();
while(!isdigit(a)){
if(a == '-')
flag = -1;
a = getchar();
}
while(isdigit(a))
t = t * 10 + a - '0', a = getchar();
return t * flag;
}
//inline void put(int x){
// if(x < 0) putchar('-'), x = -x;
// if(x < 10) putchar(x + '0');
// else put(x / 10), putchar(x % 10 + '0');
//}
const int N = 2005;
int a[N], k, n, m, cnt, maxx, b[N], ans;
signed main(){
// freopen("energy.in", "r", stdin);
// freopen("energy.out", "w", stdout);
// ios::sync_with_stdio(false);
// cin.tie(0); cout.tie(0);
cin >> n >> m >> k;
for(int i = 1; i <= n; i++)
cin >> a[i], maxx = max(a[i], maxx);
for(int i = 1; i <= maxx; i++){
cnt = 0;
for(int j = 1; j <= n; j++){
b[j] = a[j] % i;
cnt += a[j] / i;
}
if(cnt <= m - k) ans = max(ans, 0);
else if(cnt > m) ans = max(ans, k * i);
else{
int sum = (cnt - m + k) * i;
sort(b + 1, b + n + 1);
for(int j = n; j > n - m + cnt; j--)
sum += b[j];
ans = max(ans, sum);
}
}
cout << ans;
return 0;
}
/*
*/

浙公网安备 33010602011771号