毒瘤计数题汇总

2020.9.26 开始写此文以试图挽救我那可怜的计数

loj #6069 塔

首先考虑塔的顺序固定了以后的方案数。假设当我们把塔“压”到最紧的时候塔所占用的区域长为 \(k\),那么我们剩下要做的就只剩下把剩余的空间分配给每个塔了。直接插板法统计即可。显然:

\[k = 1 + \sum_{i < n}\max(h_i,h_{i+1}) \]

我们可以枚举全排列,每次 \(O(n)\) 统计,复杂度为 \(O(n! \times 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\),转移:

\[\begin{aligned} f(i-1)(j)(k) (\times (j + 1)) &\to f(i)(j+1)(k)\\ (\times 2j) &\to f(i)(j)(k+i)\\ (\times (j-1)) &\to f(i)(j-1)(k+2i) \end{aligned}\]

最终 \(f(n)(1)(k)\) 即为我们想要的排列数。

NOIP模拟赛T2 树上的僵尸

树上找 \(m\) 条不超过 \(k\) 的路径,且不存在一个点 \(p\) 被所有路径经过的方案数。\(k < n \le 10^3,m\le 10^9\)

考虑容斥。不超过 \(k\) 的路径数容易求出,记为 \(tot\),那么显然总方案数即为 \(tot^m\)。现考虑计算不合法方案。

方法一(jzp)

我们尝试用类似二项式反演的方法来减去不合法方案。显然如果存在一些点被所有路径经过,这些点一定组成一条链。设 \(g_i\) 表示这条链长为 \(i\)(边数为 \(i\))的方案数。但是 \(g_i\) 仍然难在多项式时间内算出,于是我们设 \(f_i\) 表示我们钦定长为 \(i\) 的链被所有路径经过的方案数。显然 \(f_i\) 会多算很多东西,\(f,g\) 有关系式:

\[f_i = \sum_{d \ge i}(d-i+1)g_d \]

发现并不是二项式反演的标准式子,但是仔细观察发现:

\[\begin{aligned} f_0 &= g_0 + 2g_1 + 3g_2 + 4g_3 + ...\\ f_1 &= g_1 + 2g_2 + 3g_3 + 4g_4 + ... \end{aligned}\]

而总的不合法方案数为:

\[g_0 + g_1 + g_2 + ... \]

于是 \(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)\))。

\[f(i)=A_{2^n-1}^{i-1}-f(i-1)-f(i-2)(i-1)(2^n-i+1) \]

递推即可。

Uniformly Branched Trees

给定 \(n\)\(d\),求有多少个 \(n\) 个点的不同构的树,满足所有节点的度数不是 \(1\) 就是 \(d\)

这里给出不同构的定义:树 \(A\) 和树 \(B\) 不同构,当且仅当不存在一种编号到编号的映射关系 \(p_i\),使得 \(A\) 中的边 \((u_i,v_i)\) 对应 \(B\) 中的边 \((p_{u_i},p_{v_i})\)

\(1 \le n \le 1000, 2 \le d \le 10\)

题意中要求的是无标号无根树计数,prufer序列是用来搞有标号无根树的,不好使。因此我们需要再找其它方法。

无根树实在太难搞了,我们需要将其转化为有根树。为了不重不漏地计数,我们需要找到无根树的独一无二的点:重心(至少在奇数个点的树中是这样的)。

\(f(i,j,k)\) 表示 \(i\) 个点的树,有 \(j\) 个子树,子树大小不超过 \(k\) 的方案数。这样的话最终答案(假设只有一个重心)为 \(f(n,d,n/2)\)

考虑转移。考虑子树中最大的大小是否为 \(k\),如果比 \(k\) 小,那么方案为 \(f(i,j,k-1)\);如果为 \(k\),可以枚举有几棵子树的大小为 \(k\)。设有 \(t\) 棵子树的大小为 \(k\),那么剩余的方案数应该是 \(f(i-tk,j-t,k-1)\),现在考虑 \(t\) 棵子树大小均为 \(k\) 的方案数。

发现这实质上是“\(n\) 种球,每种球有无限个(可重复),在其中拿 \(k\) 个的方案数”。如果不让重复拿一种球,那就太水了,直接组合数即可。但是我们可以给拿过的球一些重复拿的机会。现在这里给出一种做法:

\(n\) 个球后面再放 \(k-1\) 个特殊球,从总共的 \(n+k-1\) 个中拿出 \(k\) 个的方案数即为所求。即,方案数为 \({n+k-1 \choose k}\)

现在给出证明:

  • 拿普通球表示选那个球一次;拿第 \(i\) 个特殊球表示(所有拿出来的球中)第 \(i+1\) 个球和第 \(i\) 个球相同。因此一种情况唯一对应一种合法方案。
  • 对于一种合法方案,显然也唯一对应我们这里的一种情况。

2020.10.29 Update:

从Alansp那里学到了一种更好的理解方式:

考虑插板。这个问题可以转化为将 \(k\) 个无标号球涂成 \(n\) 种颜色,每个球必须涂色,每种颜色不一定需要被涂,的方案数。那么就又可以转化为了 \(k\) 个球分成 \(n\) 个集合,集合可空,的方案数。这时可以直接用插板法解决,方案数为 \({k + n - 1 \choose n - 1}\)


现在我们得到了完整的DP式子:

\[f(n,i,1)=1;f(1,0,i)=1;\\ f(i,j,k) = f(i,j,k-1) + \sum_{t \ge 1} f(i-tk,j-t,k-1) \times {f(k,d-1,k)+t-1 \choose t}\ \]

如果这棵树的点数为奇数,我们这样做没有问题。如果为偶数,我们可能会多算一些东西。不过当这棵树点数为偶数,并且有两个重心的时候,这两个重心见一定有一条边直接相连,且这条边两边的树的大小一样。如果这两棵树的方案相同,我们不会计重(可以考虑找到我们假设一个重心时最大的那棵大小为 \(n/2\) 的子树,那个子树完全相同,且外面情况完全相同,因此单重心的时候不会计算两次);如果这两棵树的方案不同,那么我们会计重。于是我们需要减去两棵树中不同的方案对数,即 \({f(n/2,d-1,n/2) \choose 2}\)

那么最终完整的答案应该为:

\[Ans = f(n,d,\lfloor \frac{n}2 \rfloor) - [2 | n] {f(n/2,d-1,n/2) \choose 2} \]

还有个小细节:这题多次用到 \(n\) 巨大 \(m\) 巨小的组合数 \({n \choose m}\)。这个是可以拆开算的:\(\dfrac{(n-m+1)...n}{m!}\)。然后发现这里 \(n\) 是可以取模的,因此我们就可以放心大胆地对 \(f\) 进行取模了。

复杂度:\(O(n^2d^2)\)(组合数暴力求的话是 \(O(n^2d^3)\) 的)。但是实际上合法的方案数并不多,记搜或许会更快些。然而我写了个刷表法被卡了qaq(尽管后来发现是求组合数的时候没有判 m > n 的情况导致出现一些玄学问题)

总之这题还是挺神的,需要用到好多计数技巧,还需要严谨的思维来判断是否算多是否少算。熟练掌握计数方法的人可能会觉得这题难度一般,但是对于我来说还是很难的,觉得不止有 \(2700\) 。或许对于zzz和lsr来说根本没 \(2500\) 吧。

On the Bench

给定长为 \(n\) 的序列 \(a_i\),问有多少种 \(i \to p_i\) 的映射方法,使得映射后的序列 \(a_{p_i}\) 中相邻两项之积都不是完全平方数。

\(n \le 300,1 \le a_i \le 10^9\)

限制等价于将 \(a_i\) 中的最大完全平方因子除去后相邻两项不能相同。

现假设值相同的 \(a_i\) 之间无标号。(最后需要乘上 \(\prod cnt_i\) 变为有标号方案数)那么题意转化为 \(m\) 中颜色的球,每种颜色有 \(a_i\) 个,共 \(n\) 个,同种颜色的球内部无区别,要求相邻的球颜色不同的方案数。

考虑容斥。设 \(f_i\) 表示恰好有 \(i\) 对相邻的数的方案数,\(g_i\) 表示钦定 \(i\) 对相邻的数的方案数。钦定的话一种恰好有 \(j\) 对相邻数的情况会被统计 \({j \choose i}\) 遍。于是有:

\[g_i = \sum_{j \ge i} {j \choose i} f_j\\ f_i = \sum_{j \ge i} {j \choose i} (-1)^{j-i} g_j \]

最终答案为 \(f_0\)

现在问题转化为求 \(g_j\),即钦定 \(j\) 对相邻的方案数。

钦定 \(j\) 对相邻可以理解为我们把 \(j\) 对球黏一块,剩下 \(n-j\) 个球。我们可以枚举每种颜色的球的黏的数量 \(b_i\),将 \(a_i\) 个球黏 \(b_i\) 的方案数等价于将 \(a_i\) 个无标号球划分为 \(b_i\) 个有标号集合(集合有标号实际上是为了钦定相对位置)的方案数,可以用插板法解决。方案数为 \({a_i - 1 \choose a_i - b_i - 1}\)

最后把每种颜色合并一下,还需要乘多重集排列(其实是一堆组合数乘一块)的系数:

\[g_j = \sum_{\sum_{b_i} = j}\prod_i {a_i-1 \choose a_i - b_i - 1} \times \frac{(\sum_{i}a_i-b_i)!}{\prod_i(a_i - b_i)!} \]

看起来 \(a_i-b_i\) 多次出现,那么把 \(b_i\) 转化为 \(a_i - b_i\)

\[g_j = \sum_{\sum_{a_i-b_i} = j}\prod_i {a_i-1 \choose b_i - 1} \times \frac{(\sum_{i}b_i)!}{\prod_ib_i} \]

然后看到多重集排列想到上EGF:

\[g_i = \prod_i G_i(x)[\frac{x^{n-i}}{(n-i)!}] \]

其中

\[G_i(x) = \sum_k {a_i - 1 \choose k-1} \frac{x^k}{k!} \]

因为 \(n\) 非常小,可以暴力卷积。复杂度:\(O(n^3)\)

posted @ 2020-09-26 11:35  JiaZP  阅读(291)  评论(0编辑  收藏  举报