D. Colored Balls
D. Colored Balls
There are balls of different colors; the number of balls of the -th color is .
The balls can be combined into groups. Each group should contain at most balls, and no more than ball of each color.
Consider all sets of colors. For a set of colors, let's denote its value as the minimum number of groups the balls of those colors can be distributed into. For example, if there are three colors with , and balls respectively, they can be combined into groups (and not less than ), so the value of that set of colors is .
Your task is to calculate the sum of values over all possible sets of colors. Since the answer may be too large, print it modulo .
Input
The first line contains a single integer () — the number of colors.
The second line contains integers () — the number of balls of the -th color.
Additional constraint on input: the total number of balls doesn't exceed .
Output
Print a single integer — the sum of values of all sets of colors, taken modulo .
Examples
input
3
1 1 2
output
11
input
1
5
output
5
input
4
1 3 3 7
output
76
Note
Consider the first example. There are sets of colors:
- for the empty set, its value is ;
- for the set , its value is ;
- for the set , its value is ;
- for the set , its value is ;
- for the set , its value is ;
- for the set , its value is ;
- for the set , its value is ;
- for the set , its value is .
So, the sum of values over all sets of colors is .
解题思路
题目给出的组合规则其实就是摩尔投票。即确定颜色的方案后,假设球的总数为 ,所有颜色中数量最多的球有 个,则分组数量的最小值分两种情况:
- 如果 ,则至少分成 组。
- 如果 ,则至少分成 组。
更新:该定理的扩展可参考 A. Cards Partition。
所以我们可以对数组 升序排序,固定数量最多的球 ,用 来表示所有不超过 的球(即 )组成总数为 的方案数量。那么以 作为数量最多的球的所有方案中,贡献的答案是(其中 ):
其中 根据是否选择 进行状态划分(01 背包),转移方程为 。
AC 代码如下,时间复杂度为 :
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 5005, mod = 998244353;
int a[N];
int f[N][N];
int main() {
int n, m = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
m += a[i];
}
sort(a + 1, a + n + 1);
int ret = 0;
f[0][0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= m; j++) {
if (j >= a[i]) ret = (ret + (j + a[i] + 1ll) / 2 * f[i - 1][j]) % mod;
else ret = (ret + 1ll * a[i] * f[i - 1][j]) % mod;
f[i][j] = f[i - 1][j];
if (j >= a[i]) f[i][j] = (f[i][j] + f[i - 1][j - a[i]]) % mod;
}
}
printf("%d", ret);
return 0;
}
参考资料
Educational Codeforces Round 164 (Rated for Div. 2) A~E - 知乎:https://zhuanlan.zhihu.com/p/692227075
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/18132986
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2022-04-13 查询字符串
2021-04-13 Saving James Bond - Hard Version