设题目中给出的 \(1\) 的个数占总数的 \(\frac{m}{k}\)。考虑一个最朴素的 \(O(n^3)\) dp:设 \(f_{i,j}\) 表示选择了 \(i\) 个,总和为 \(j\) 是否存在。
当我们用 \(j-i\) 代替 \(j\) 的时候显然答案不会被改变,而好处在于可以把 \(1\) 拉出来单独考虑。当我们不考虑 \(1\) dp 完这个数组后,对于每个 \(j\),只有 \(O(k)\) 个 \(i\) 需要被考虑。具体的,初始化 \(x=\infty\),设 \(1\) 有 \(p\) 个,则每次找到最大的小于等于 \(x+p\) 的数,则 \(x\) 到这个数之间都能被覆盖到,并把 \(x\) 赋值为这个数,若找不到则找最小的大于等于 \(x+p+1\) 的数,这个区间内只有 \(p+1\) 个数为 \(1\),然后将 \(x\) 赋值为这个数。容易发现至多只有 \(2k\) 个 \(i\) 被考虑到。
但是这对我们的 dp 并没有什么实质性的帮助。考虑对 dp 本身进行优化,一般有 bitset 或者多重背包。bitset 与上述过程并没有很大的关联,所以考虑多重背包,这样需要考虑的物品数只有 \(O(\sqrt m)\) 个。对于每个物品,用 set 维护一个滑动窗口内可以转移的数,在里面二分即可转移。时间复杂度 \(O(n\sqrt nk\log n)\) 但是实际上并跑不满。
标签:6355,sqrt,bitset,考虑,QOJ,dp From: https://www.cnblogs.com/275307894a/p/17660706.html