题解 CF1954D Colored Balls

Thearticlediscussesanalgorithmforgroupingballsbasedoncolor,aimingtominimizethenumberofgroupsusingdynamicprogramming.Itexplainstheprocessofsorting,statetransitionfunction,andspace-savingtechniques.

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于单个set方案,每次分group时,如果有不同颜色可以把两个球分到同一个group,如果只剩一个颜色则只能一个球一个group。那么最优的分法是每次数量最少的球和数量最多的球分同一个group,直到分完或者分到只剩一种颜色的球,如果只剩一种颜色则这些球每一个成一个group。

对于单个set方案,假设 x x x 是方案里数量最多的颜色的球的数量, y y y 为其它球数量,则这个set方案的value(最小group数)为

max ⁡ ( x , ⌈ x + y 2 ⌉ ) . \mathop{\max}(x,\lceil \frac{x+y}{2} \rceil). max(x,2x+y⌉).

接下来,要得到题目所问结果,我们需要把所有可能方案的value求和。方案数有 2 n 2^n 2n 种,我们不可能一个一个枚举,这种涉及到求方案数的题可以考虑DP。

先把 a a a 数组从小到大排一个序,以保证第一次遍历到 a i a_i ai 时它是目前已考虑方案的最大值。而且题目保证 ∑ i = 1 n a i ≤ 5000 \sum_{i=1}^n a_i \le 5000 i=1nai5000 ,可以考虑对球数遍历。

一种可行的状态转移函数是, f i , j f_{i,j} fi,j i i i 表示遍历到的 a i a_i ai 的下标, j j j 表示当前球数, f i , j f_{i,j} fi,j 函数值表示这个状态的方案数,这个方案数用DP很容易求出。

我们用状态 j j j 代替之前式子中的其它球数量 y y y a i a_i ai 由于排过序,遍历到的时候保证是set中数量最多的颜色的球的数量,则每一次访问一个状态要对结果加上

max ⁡ ( a i , ⌈ a i + j 2 ⌉ ) × f i − 1 , j . \mathop{\max}(a_i,\lceil \frac{a_i+j}{2} \rceil) \times f_{i-1,j}. max(ai,2ai+j⌉)×fi1,j.

i i i 维度的空间可以用 j j j 的逆向遍历优化节省掉。最后得到了以下代码:

#include <bits/stdc++.h>
#define ll long long
#define MOD 998244353
using namespace std;
int n,a[5010];
ll f[5010];
int main() {
	cin>>n;
	for (int i=1;i<=n;++i) cin>>a[i];
	sort(a+1,a+1+n);
	memset(f,0,sizeof(f));
	f[0] = 1;
	ll ans = 0;
	for (int i=1;i<=n;++i){
		for (int j=5000-a[i];j>=0;--j){
			ans = (ans + max(a[i],(int)ceil((double)(j+a[i])/2.0))*f[j]%MOD)%MOD;
			f[j+a[i]] = (f[j+a[i]] + f[j])%MOD;
		}
	}
	cout<<ans<<endl; 
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值