#summer40008. 银狼的多重背包
银狼的多重背包
Problem Description
你学习了多重背包问题。该问题的描述是这样的:
给定 $n$ 个物品,其中第 $i$ 种物品的数量是 $c_i$ 个,花费为 $w_i$ 元,它的价值是 $v_i$。你身上带了 $m$ 元钱。你想要在物品总花费不超过 $m$ 元的情况下最大化所拿去物品的价值。
$1 \le n \le 100$,$1 \le m \le 4 \times 10^4$,$\sum c_i \le 10^5$,$1 \le v_i, w_i \le 1000$
精通动态规划的你,很容易想到一个如下的解法:
for (int i = 1; i = 0; j--) {
dp[i][j] = max(dp[i][j], dp[i - 1][j]);
for (int k = 0; k = 0; k++) {
dp[i][j] = max(dp[i][j], dp[i - 1][j - k * w[i]] + 1ll * k * v[i]);
}
}
}
很明显,这段代码的时间复杂度是 $O(n m \sum c_i)$,远远无法通过本题。
于是,你请教了 Silverwolf 老师,她教了你一种二进制拆分优化多重背包的方法。对于每个物品 $c_i$,都具有唯一的一种拆解方式,具体方式如下:
$\quad$**·** 找到满足 $2^{K} - 1 \le c_i$ 的最大的正整数 $K$ $\quad$**·** 将 $c_i$ 拆解出 $1, 2, 4, ..., 2^{K-1}$ $\quad$**·** 若 $c_i - 2^{K} + 1 > 0$,则拆解出余项数 $c_i - 2^{K} + 1$容易证明,这样的拆分方式是唯一的。设 $cnt_i$ 表示 $c_i$ 拆分出的项数。例如,对于 $c_i=11$,其唯一的拆分方案是 $(1,2,4,4)$,故 $cnt_i=4$。
于是你得到了二进制拆分优化多重背包的代码:
for (int k = 1; k <= m; k <<= 1) {
m -= k;
// do sth
}
if (m) {
// do sth
}
在教完你该问题后,Silverwolf 老师考了你一个问题,也就是本题的内容。
给定 $n$ 和 $C$,你需要构造一个非负整数序列 $c_1, c_2, ..., c_n$,满足 $\sum_{i=1}^n c_i = C$,使得 $\sum_{i=1}^n cnt_i$ 最大。你只需要输出任意一种使得 $\sum cnt_i$ 最大的分配方案。
Input Format
第一行一个整数 $T$($1 \le T \le 500$),表示测试数据组数。
接下来 $T$ 行,每行两个整数 $n, C$($1 \le n \le 100$,$1 \le C \le 10^5$),分别表示物品数量上限和 $\sum c_i$ 的总和。
Output Format
对于每组测试数据,输出一行 $n$ 个非负整数 $c_1, c_2, ..., c_n$,满足 $\sum c_i = C$,且 $\sum cnt_i$ 最大。如果有多组合法方案,输出任意一组即可。
2
2 6
3 5
4 2
2 2 1