加载中...

题解: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;
}
/*
*/
posted @ 2025-11-17 18:47  碎碎念的女巫  阅读(24)  评论(0)    收藏  举报