ㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙㄧㄨㄩㄚㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦ ˊˇˋ

「KDOI-11」彩灯晚会

首先这个分别平方再求和比较烦。考虑平方的组合意义就是在图上选出两条可重合的同色链,那么我们就只需要在图上选两条链,染成相同的颜色,然后剩下的点随便染就行了。对于选出来的两条链,染色方案为 \(k^{n-(2l-c)+1}\),其中 \(c\) 是两条链的交点个数。

两条链可以看作两个人在图上分别走出两条长度为 \(l\) 的路径,所以我们考虑设出状态描述当前走的情况。设 \(f_{u,v,a,b}\) 表示两个人分别走到 \(u,v\),当前两个人走的长度分别是 \(a,b\) 的染色方案数,初值赋为 \(k^{n+1}\),每走到一个点就除以 \(k\),交点只除一次。但是如果我们随便走的话,可能会出现交点没有统计到的情况。我们发现每走一步拓补序都会变大,所以我们考虑每一步让字典序小的那个人走,相同就第一个人走,这样就不会漏交点了。这样做时间复杂度是 \(O(n^3 l^2)\) 的,过不了且难以优化。

如果记两个点算上转移就至少是 \(O(n^3)\) 的,没有前途。我们发现其实我们只关心交点在哪里,不是交点的情况我们并不关心。这样我们可以考虑状态里只记交点,然后交点之间直接乘上路径方案数就行。但是枚举的交点之间可能又会经过交点,导致算漏。又因为我们要算交点数量恰好等于 \(c\) 的方案数,所以我们考虑容斥,计算钦定 \(c\) 个交点,也就是 \(\geq c\) 的交点的方案数。设 \(f_{i,c,x,y}\) 表示当前交点为 \(i\),钦定了 \(c\) 个交点,当前两个人分别走了 \(x,y\) 步的方案数。对于起点和终点不同的问题,我们只需要建一个超级源点和超级汇点,让链长度加 \(2\) 即可。转移比较简单,我们预处理 \(g_{i,j,x}\) 表示从 \(i\)\(j\) 长度为 \(x\) 的路径方案数,转移就是 \(f_{i,c,x,y} \times g_{i,j,\Delta_x,\Delta_y} \to f_{j,c+1,x+\Delta_x,y+\Delta_y}\)。这样做是 \(O(n^2 l^5 + n^3 l)\) 的,看起来更劣了,但是我们成功将 \(n\) 降到了两次。考虑优化,我们发现其实转移是一个二维卷积,\(\Delta_x\)\(\Delta_y\) 之间没有关联,那么我们可以分两步转移,先加 \(x\)\(\Delta_x\),再加上 \(y\)\(\Delta_y\),这样就可以做到 \(O(n^2 l^4 + n^3 l)\),但还是过不了。

我们考虑从计算答案上下手。设 \(f_i\) 表示恰好有 \(i\) 个交点的方案数,\(g_i\) 表示钦定 \(i\) 个交点的方案数,则有:

\[f_i = \sum\limits_{j=i}^{l} (-1)^{j-i} \binom{j}{i} g_j \]

答案为:

\[\begin{aligned} & \space \space \space \space \thinspace \sum\limits_{i=0}^{l} k^{n-2l+i+1} f_i \\ &= k^{n-2l+1} \sum\limits_{i=0}^{l} k^i \sum\limits_{j=i}^{l} (-1)^{j-i} \binom{j}{i} g_j \\ &= k^{n-2l+1} \sum\limits_{i=0}^{l} g_i \sum\limits_{j=0}^{i} \binom{i}{j} (-1)^{i-j} k^j \\ &= k^{n-2l+1} \sum\limits_{i=0}^{l} g_i (k-1)^i \end{aligned} \]

此时发现可以不记录钦定的交点数量了,每经过一个交点转移的时候乘上 \(k-1\) 就行了,这样可以做到 \(O(n^2 l^3 + n^3 l)\),卡卡常就能过了。

技巧:

  • 平方计数可以考虑组合意义。
  • 需要记录共同的信息(如交点),正常做法难以优化时,可以考虑容斥,只计交点,然后钦定交点个数。
  • 转移难以优化时可以考虑从计算答案优化入手,发现性质。
  • 需要记录具体的(钦定的)点的数量时,可以考虑如何不记点数。

「KDOI-03」构造数组

如果我们已经知道了操作的点对是哪些,那么计算答案相当于是多重集排列。设 \(m = \sum\limits_{i=1}^{n} b_i\)。显然 \(m \equiv 1 \pmod 2\) 无解。一种点对集合的答案计算为:

\[\frac{(\frac{m}{2})!}{\prod_{1 \leq x < y \leq n} c_{x,y}!} \]

其中 \(c_{x,y}\) 表示操作 \((x,y)\) 的数量。

发现这个方向不好做,因为如果我们顺序 DP 每一个数,我们就需要知道之前每一个数具体剩下多少,爆掉了,而且阶乘非常难拆。

我们考虑直接 DP 操作序列。操作序列相当于是从左到右 \(\frac{m}{2}\) 个二元组,我们每次考虑将一种相同的数全部填进去。那么我们需要知道当前剩下的已占用 \(0/1/2\) 个元素的二元组数量,而我们发现如果我们知道了已占用 \(1\) 个元素的二元组数量 \(j\),由于我们是顺序填入一种数,所以占用 \(2\) 个的二元组的数量为 \(\frac{sum_i-j}{2}\),其中 \(sum_i\) 是前 \(i\) 种数的数的个数和,那么占用 \(0\) 个的也能算。设 \(f_{i,j}\) 表示填了前 \(i\) 种数,占用了 \(1\) 个元素的二元组数量为 \(j\) 的方案数。转移枚举上一次的 \(j\),再枚举当前多少个数填入之前占用 \(1\) 个的二元组即可。外层枚举 \(n\),内层先枚举二元组数量是 \(O(m)\) 的,然后再枚举填入数量,不超过 \(b_i\),发现最内层和最外层的总枚举量为 \(O(m)\),总时间复杂度为 \(O(m^2)\)

技巧:

  • 阶乘难以拆开。
  • 对于执行操作的 DP,可以考虑 DP 操作序列。
  • 状态记录过多时可以考虑是否由一些信息可以直接推出另一些信息,避免冗余状态。

【MX-X13-T6】「KDOI-12」能做到的也只不过是静等缘分耗尽的那一天。

做法可以看题解。

总结一下技巧:如果有形如 \(\frac{1}{ab}\),其中 \(b-a = c\)\(c\) 为常数,那么:

\[\frac{1}{ab} = \frac{1}{b-a} \times \frac{b-a}{ab} = \frac{1}{b-a}(\frac{1}{a} - \frac{1}{b}) \]

实际上就是裂项。

再总结一个。

我们知道:

\[\sum\limits_{i=0}^{n} \binom{i}{m} = \binom{n+1}{m+1} \]

那么:

\[\begin{aligned} \sum\limits_{i=0}^{n} i \binom{i}{m} &= \sum\limits_{i=0}^{n} \sum\limits_{j=i+1}^{n} \binom{j}{m} \\ &= \sum\limits_{i=0}^{n} \binom{n+1}{m+1} - \binom{i+1}{m+1} \\ &= (n+1) \binom{n+1}{m+1} - \sum\limits_{i=1}^{n+1} \binom{i}{m+1} \\ &= (n+1) \binom{n+1}{m+1} - \binom{n+2}{m+2} \end{aligned} \]

posted @ 2025-12-15 14:31  gevenfeng  阅读(17)  评论(0)    收藏  举报