2020.9.26 开始写此文以试图挽救我那可怜的计数
loj #6069 塔
首先考虑塔的顺序固定了以后的方案数。假设当我们把塔“压”到最紧的时候塔所占用的区域长为 (k),那么我们剩下要做的就只剩下把剩余的空间分配给每个塔了。直接插板法统计即可。显然:
我们可以枚举全排列,每次 (O(n)) 统计,复杂度为 (O(n! imes n)),这仅比暴力的 (O(d^n)) 要好些,不过至少与 (d) 无关了。
现在我们需要知道对于每个 (k) 的排列数。根据套路,我们将 (h) 从小到大排序后依次插入,这样当 (i) 插入的时候其余的塔就都可以看作一样的了,该塔对 (k) 的贡献即为两边比它小的塔的个数。但是我们还需要知道当前这个 (i) 还能往哪几个地方插入能够“在旁边有比它小的塔”。我们可以记空隙的个数为 (j),当然也可以记“段”的个数为 (j)。即我们把DP过程看作不断加入并产生/合并段的过程,最终合并成一个段。
状态:(f(i)(j)(k)) 表示插入了前 (i) 个塔,当前有 (j) 个段,(k) 值为 (k) 的排列数。初始化:(f(1)(1)(1) = 1),转移:
最终 (f(n)(1)(k)) 即为我们想要的排列数。
NOIP模拟赛T2 树上的僵尸
树上找 (m) 条不超过 (k) 的路径,且不存在一个点 (p) 被所有路径经过的方案数。(k < n le 10^3,mle 10^9)
考虑容斥。不超过 (k) 的路径数容易求出,记为 (tot),那么显然总方案数即为 (tot^m)。现考虑计算不合法方案。
方法一(jzp)
我们尝试用类似二项式反演的方法来减去不合法方案。显然如果存在一些点被所有路径经过,这些点一定组成一条链。设 (g_i) 表示这条链长为 (i)(边数为 (i))的方案数。但是 (g_i) 仍然难在多项式时间内算出,于是我们设 (f_i) 表示我们钦定长为 (i) 的链被所有路径经过的方案数。显然 (f_i) 会多算很多东西,(f,g) 有关系式:
发现并不是二项式反演的标准式子,但是仔细观察发现:
而总的不合法方案数为:
于是 (f_0 - f_1) 即为答案。其中 (f_0,f_1) 均可以 (O(n^2)) 快速算出。
方法二(zzz & std)
考虑对于每条链,我们仅在其最浅的那个点(LCA)处计算贡献。枚举那个 LCA,答案即为“所有路径均经过 LCA” - “所有路径均经过 LCA 及其父亲”。直接算即可。
有趣的是,最后算的东西其实与方法一相同。
卡农
可以先算出合法“序列”的数量,最后除以阶乘即可。
考虑DP。设 (f(i)) 表示长为 (m) 的合法的“序列”个数。合法的意思是:无空集;不重复;每个元素都出现了偶数次。
考虑容斥求 (f(i))。如果我们能够找出前 (i-1) 个元素(共 (A_{2^n-1}^{i-1}) 种方案),那么根据“每个元素都出现偶数次”,可以确定最后一个集合是什么。但是可能会有不合法的情况。可以将不合法的情况分为两种:出现重复(最后一个集合与之前某个集合重复,去除重复后恰好是 (f(i-2)),故方案数为 (f(i-2)(i-1)(2^n-1-(i-2))));最后那个集合为空((f(i-1)))。
递推即可。