【题解】QOJ 5097 [集训队互测 2022] 小 P 爱学习
#5097. [集训队互测 2022] 小 P 爱学习
题意
有 \(nm\) 个物品,第 \(i\) 个物品有一个权值 \(a_i\)。
请你把这些物品分成若干无序的组,使得每一组的物品数量都是 \(m\) 的倍数。
一个分组方案的价值为所有组内的物品权值和的乘积。
请你求出对于所有分组方案,其价值的和对 \(10^9+7\) 取模的值。
两个分组方案不同当且仅当存在两个物品在一个分组方案中被分进了同一组而另一个分组方案中不在同一组。
\(n\le 1500,m\le 100,a_i\in [0,10^9+7)\)。
题解
知识点:动态规划,排列组合,根号分治
启发:
-
通过钦定一种顺序将有序表达为无序。
-
根号分治平衡 dp 转移。
-
对 dp 状态归一化减少转移常数。
集训队互测题总能看到一些意想不到的知识点搭配。
质量很高的一题,这里提供每一档部分分的讲解。
\(n,m\le 4\)
推得 \(nm\le 16\),可以用一个二进制数表示每个物品选或者不选的状态。
设 \(dp_s\) 为当前状态为 \(s\) 时的价值和,这里不关心分组数,因为求解答案的过程中没有直接和分组数相关联的因素。
特别地,\(dp_0=1\)。
从 \(1\) 到 \(2^{nm}-1\) 枚举 \(s\),对每个 \(s\) 枚举子集 \(t\),即枚举分这一组之前的状态,则 \(s-t\) 就可以表示这一组所选的物品。
令 \(\operatorname{calc(s)}\) 表示 \(s\) 每个为 \(1\) 的位对应的物品的价值之和,\(\operatorname{popcount(s)}\) 表示 \(s\) 中为 \(1\) 的位置个数,即选择的物品个数。
由于题目认为组之间是无序的,而枚举 \(s\) 的子集 \(t\) 并都进行转移显然是默认有序的,需要更正。
令 \(\operatorname{lowbit(s)}\) 表示提取出 \(s\) 最低位的 \(1\),更高位全部抛弃(如 \(\operatorname{lowbit((110)_2)}=(10)_2\)),如果你学过树状数组,那你一定知道 \(\operatorname{lowbit(s)}=(-s)\&s\)。
考虑钦定 \(s\) 最低位选择的物品必须选,即应该有 \((s-t)\&\operatorname{lowbit(s)}>0\),这相当于钦定了顺序,固定的一种顺序也就能看作无序了。
由此得出转移方程:
答案即为 \(dp_{2^{nm}-1}\)。
在这题状压 dp 比搜索更为好写,不过都是对题目性质探索不足的无奈之举罢了。
使用枚举子集的经典方法,对每个状态枚举子集,总时间复杂度为 \(O(3^{nm})\),可以通过这档分。
\(m=1\)
\(m=1\),相当于没有对组内物品数量特征作限制,只需要大于 \(0\) 即可。
考虑一种分组方案,一共分了 \(k\) 组,第 \(i\) 组有 \(l_i\) 个物品,分别为 \(p_{1,i},p_{2,i},...,p_{l_i-1,i},p_{l_i,i}\)。
则对答案的贡献为:
考虑组合意义,相当于对每一组都选出一个物品,将其权值相乘,贡献到答案,总贡献就是所有选法的贡献之和。
反过来考虑,钦定 \(k\) 个物品 \(p_1,p_2,...,p_k\)(由于组间无序,物品编号应递增,意义是通过钦定一种有序的情况来代表无序),各自分到共 \(k\) 个组中,设在该情况下的分组方案数为 \(res\),则其对答案的贡献是 \(\displaystyle res\times \prod_{i=1}^k a_{p_i}\),为了方便叙述,设 \(\prod_{i=1}^k a_{p_i}\) 为初始贡献。
由于 \(m=1\),剩下未钦定的 \(n-k\) 个物品可以随便选分到哪个组,则 \(res\) 只与总组数(即 \(k\))有关。
设 \(g_k\) 为已经钦定了 \(k\) 个物品的情况下(分了 \(k\) 个组),剩余物品的分组方案数。
则 \(g_k=k^{n-k}\)。
设 \(dp_{i,j}\) 为考虑了前 \(i\) 个数,钦定了 \(j\) 个数(分了 \(j\) 个组)时的初始贡献之和,则有如下转移:
则答案为:
这一档分对正解提示性比较大,而 \(dp_{i,j}\) 也是正解所需要用到的,总时间复杂度 \(O(n^2m)\),由于 \(m=1\),可以看作 \(O(n^2)\)。
\(n\le 100\) 与 \(n\le 500\)
\(m\) 不一定为 \(1\),这对组内物品数量特征起到了限制,不过 \(g_k\) 仍然只与分组数 \(k\) 有关,这启发去用其他方式求出 \(g_k\)。
既题目要求组内物品数一定是 \(m\) 的倍数,那不妨直接在倍数的基础上做。
设 \(cnt_{i,j}\) 为在前 \(i\) 个组中,一共放入了 \(jm\) 个物品的分组方案数。
需要注意的是,放入的 \(jm\) 个物品中,有 \(i\) 个是已经被钦定好的,可看作 \(i\) 个无标号不参与排列组合的小球,而剩下的 \(jm-i\) 个数则可看作有标号参与排列组合的小球。
那么就有转移:
那么 \(g_k=cnt_{k,n}\)。
注意到此时 \(nm\times n\) 比较大,不妨在处理 \(dp_{i,j}\) 的时候使用滚动数组,毕竟最后也只需要用到 \(dp_{n,i}\),那么下文默认 \(dp_i\) 为滚动之后的 \(dp_{n,i}\)。
最后的答案就是:
能否通过 \(n\le 500\) 那档,取决于算组合数那块的复杂度是否是单次 \(O(1)\)。
总复杂度 \(O(n^2m+n^3)\)。
\(n\le 1500\)
处理 \(dp_{i}\) 的那部分时间复杂度 \(O(n^2m)\) 没问题,问题在于对 \(cnt_{i,j}\) 的处理比较慢,是 \(O(n^3)\) 的。
注意到最终计算答案的那个部分是 \(O(n)\) 的,即 \(g_k\) 单次计算的复杂度是 \(O(1)\) 的,能否让这部分复杂度增高,使得对 \(cnt_{i,j}\) 的处理复杂度降低,达到一个平衡的效果呢?
考虑设定一个阈值 \(B\),并将 \(cnt\) 数组分裂成两个数组 \(cnt1\) 和 \(cnt2\),进行如下状态设计。
\(cnt1_{i,j}\) 为在前 \(i\) 个组中,一共放入了 \(jm\) 个物品的分组方案数,每个组至多放入了 \(Bm\) 个物品。
\(cnt2_{i,j}\) 为在前 \(i\) 个组中,一共放入了 \(jm\) 个物品的分组方案数,每个组至少放入了 \((B+1)m\) 个物品。
那么就有转移:
那么处理 \(cnt1_{i,j}\) 的时间复杂度是 \(O(n^2B)\)。
由于每个组至少放入了 \((B+1)m\) 个物品,最多分 \(\frac{n}{B}\) 个组,则处理 \(cnt2_{i,j}\) 时 \(i\) 只需要枚举到 \(\frac{n}{B}\),时间复杂度 \(O(\frac{n^3}{B})\)。
现在考虑合并两个状态得出 \(g_i\),当分 \(i\) 个组时,枚举 \(x\) 组的大小至少为 \(B+1\),复杂度是 \(O(\frac{n}{B})\),再枚举大小至少为 \(B+1\) 的组放入了 \(ym\) 物品,复杂度是 \(O(n)\) 的。
则有如下式子:
注意后面的两个组合数,以下是解释。
\(\binom{i}{x}\) 表示从 \(i\) 个组中选 \(x\) 个分给大小至少为 \((B+1)m\) 的组,明明组间无序,为什么这里又要分配了呢?仔细想想,我们是不是在之前按编号递增顺序钦定了 \(k\) 个数,固定了一种顺序,也就成了无序。
\(\binom{nm-i}{ym-x}\) 表示从总共 \(nm-i\) 个有标号球中选出 \(ym-x\) 个分给大小至少为 \((B+1)m\) 的组,明明之前处理的时候就已经是标号的了,为什么这一还要再分配一遍呢?仔细思考,之前的标号是局部的情况,相当于对大小至多为 \(Bm\) 的组内部标号 \(1\sim (n-y)m-(i-x)\),对大小至少为 \((B+1)m\) 的组内部标号 \(1\sim ym-x\),合并的时候,又需要重新标号,即从 \(1\sim nm-i\) 个标号中选 \(ym-x\) 个顺次分配给大小至少为 \((B+1)m\) 的组。
答案即为,
当 \(B\) 取 \(\sqrt{n}\) 时,复杂度达到最优,为 \(O(n^2m+n^2B+\frac{n^3}{B})=O(n^2m+n^{2.5})\),这就是根号分治。
怎么还卡常,感觉不是很有素质
题目时间限制是 \(1.5\) 秒,如果这样写大概率会被卡常,究其根本,是因为计算一次组合数要进行三次乘法,一开始发现官解设计了一个特别奇怪的状态,于是自己想了比较正常的状态设计(就是上面的),但是卡不过去,所以在这里讲讲官解的状态设计。
设 \(f_{i,j}\) 表示为在前 \(i\) 个组中,一共放入了 \(jm\) 个物品的分组方案数乘上 \(\frac{1}{(jm-i)!}\) 的结果。
可以得出关系式 \(cnt_{i,j}=f_{i,j} \times (jm-i)!\)。
带入之前的转移式:
化简得到:
最后计算 \(g_k\) 时有,\(g_k=f_{k,n} \times (nm-k)!\)
这样写比组合数少了两次乘法,自然会快一些。
设 \(f1_{i,j}\) 为在前 \(i\) 个组中,一共放入了 \(jm\) 个物品的分组方案数乘上 \(\frac{1}{(jm-i)!}\) 的结果,每个组至多放入了 \(Bm\) 个物品。
设 \(f2_{i,j}\) 为在前 \(i\) 个组中,一共放入了 \(jm\) 个物品的分组方案数乘上 \(\frac{1}{(jm-i)!}\) 的结果,每个组至少放入了 \((B+1)m\) 个物品。
那么也可以代入平衡复杂度的那个转移式:
代入并化简:
答案即为:
还是当 \(B\) 取 \(\sqrt{n}\) 时,复杂度达到最优,为 \(O(n^2m+n^{2.5})\),由于乘法次数变少了,常数更加优秀。

浙公网安备 33010602011771号