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

「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} \]

也可以:

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

上面两个结果是一样的。因为:

\[\begin{aligned} (n+1) \binom{n+1}{m+1} - \binom{n+2}{m+2} - \Bigg[ (m+1) \binom{n+2}{m+2} - \binom{n+1}{m+1} \Bigg] &= (n+2) \binom{n+1}{m+1} - (m+2) \binom{n+2}{m+2} \\ &= \frac{(n+2)!}{(m+1)! (n-m)!} - \frac{(n+2)!}{(m+1)! (n-m)!} \\ &= 0 \end{aligned} \]

「OICon-02」Subtree Value

首先 \(a_x\) 加的数必须是 \(|S|\),是在变的,并且不好维护变化量。直接枚举 \(|S|\),然后设 \(f_{i,j}\) DP 就行了,最后对于每个 \(|S|\) 答案是 \(\sum\limits_{i=1}^{n} f_{i,|S|}\) 。可以做到 \(O(n^3)\)。过不了。

发现模数非常特殊,是 \(U^V\),且 \(U,V\) 都很小,猜想是不是乘了几次 \(U\) 之后指数大于等于 \(V\) 就没用了。我们设 \(f(S,\Delta) = \prod\limits_{u \in S} (a_u + \Delta),g(x,\Delta) = \sum\limits_{|S| = x} f(S,\Delta)\),那么答案就是 \(\sum\limits_{i=1}^{n} g(i,i)\)

\(\Delta\)\(U\) 表示。设 \(\Delta = kU + r\),那么:

\[\begin{aligned} f(S,\Delta) &= \prod_{u \in S} (a_u + kU + r) \\ &= \sum\limits_{i=0}^{|S|} \sum\limits_{T \subseteq S,|S| - |T| = i} (kU)^i \prod\limits_{u \in T} (a_u + r) \\ & \equiv \sum\limits_{i=0}^{V-1} (kU)^i \sum\limits_{T \subseteq S,|S| - |T| = i} \prod\limits_{u \in T} (a_u + r) \pmod{U^V} \end{aligned} \]

发现 \(f(S,kU + r)\) 对于相同的 \(r\) 来说是一个关于 \(k\)\(V-1\) 次多项式。因此我们可以先枚举 \(r\),然后先对于 \(x \in [1,n]\) 算出所有 \(g(x,r),g(x,U+r),g(x,2U+r),\cdots,g(x,(V-1)U+r)\),然后插值求出 \(g(x,kU + r),k \geq V\) 即可。

但是这里插值不太能取模后拉插,因为模数不是质数。但是可以发现拉插的乘法乘出来只有 \(10^{30}\),所以开 __int128 就行了。但是还有一种做法,有一个叫牛顿插值的东西。如果我们知道 \(f(1),f(2),\cdots,f(n)\),那么我们可以算出:

\[f(k) = \sum\limits_{i=1}^{n} \binom{k-1}{i-1} \sum\limits_{j=1}^{i} (-1)^{i+j} \binom{i-1}{j-1} f(j) \]

组合数不需要逆元,所以牛顿插值就可以了。时间复杂度 \(O(n^2 UV + n V^2)\)

技巧:

  • 在变化且难以维护的东西可以考虑直接去枚举。
  • 特殊模数可能有性质,特别是可以表示为一些较小底数和较小指数的乘积时。
  • 卷积的形式可以考虑插值优化。
  • 牛顿插值不需要求逆元,但需要连续点值。

【MX-X18-T5】「FAOI-R6」纯蓝

序列中任意两个数的异或最小值比较难刻画。我们希望转为特定的异或值,如相邻数的异或值。发现,如果设 \(b\) 表示 \(a\) 序列中从大到小排序后的序列,则:

\[\min\limits_{1 \leq i < j \leq n} (a_i \oplus a_j) = \min\limits_{i=1}^{n-1} (b_i \oplus b_{i+1}) \]

为什么?这个问题等价于:

\[\forall a<b<c, \min (a \oplus b,b \oplus c) < a \oplus c \]

证明不是很难。\(a,b,c\) 从高位开始有一段 \(lcp\),我们找到 \(lcp\) 后的第一位,之前的位 \(a \oplus b,b \oplus c,a \oplus c\) 都一样,那么肯定 \(a\) 这一位为 \(0\)\(c\) 这一位为 \(1\),那么 \(a \oplus c\) 这一位为 \(1\),而不管 \(b\) 这一位是 \(0\) 还是 \(1\)\(a \oplus b,b \oplus c\) 中肯定有一个这一位为 \(0\),小于 \(a \oplus c\)。于是就证完了。

那么直接考虑去 DP 排序后的序列。但是相邻异或值的最小值还是不太好搞。注意到我们的要求相当于序列每一对相邻数的异或大于等于最小值,那么由 \(x = \sum\limits_{i=0}^{x-1} 1\),我们考虑枚举一个 \(k\),然后计算 \(f(a) > k\) 的方案数,那么最小值就变成了相邻异或值的常数限制。这下就可以 \(DP\) 了。设 \(f_{i,j}\) 表示已经填了 \([1,i]\) 中的数,\(b_i = j\) 的方案数,那么转移就是:

\[f_{i,j} = (c_j - i + 1) \sum\limits_{x=j}^{V} [j \oplus x > k] f_{i-1,x} \]

其中 \(c_x = \sum\limits_{i=1}^{n} [l_i \geq x]\),就是说原先这一位 \(\geq j\) 可以用 \(c_j\)\(a\) 中的数来填,但是前面已经用过 \(i-1\)\(\geq j\) 的元素了,所以要减去 \(i-1\)。枚举 \(k\) 时间复杂度为 \(O(V)\),DP 时间复杂度为 \(O(n V^2)\),总复杂度为 \(O(n V^3)\)。发现有形如 \(a \oplus x > k\) 的形式,使用字典树可以做到 \(O(n V^2 \log V)\)

其实 DP 可以做到 \(O(nV)\)。我们枚举 \(j \oplus x\)\(k\) 最高的不相同的位 \(h\),那么比 \(h\) 位高的位 \(j \oplus x\)\(k\) 相等,第 \(h\)\(j \oplus x\)\(1\)\(k\)\(0\)。我们去枚举 \(j\) 的第 \(h\) 位和更高的位 \(j' = \lfloor \frac{j}{2^h} \rfloor\),设 \(k' = \lfloor \frac{k}{2^h} \rfloor\) 表示 \(k\) 的高于 \(h\) 的位,\(x' = \lfloor \frac{x}{2^h} \rfloor\),那么 \(x' = (k' + 1) \oplus j'\)。我们发现 \(x' \neq j'\),因为如果 \(x' = j'\),那么 \(k' + 1 =0\),但 \(k' \geq 0\),所以不可能。那么由 \(x'\)\(j'\) 就可以得出 \(x\)\(j\) 的大小关系。判掉 \(x' < j'\),那么对于 \(x' > j' , \forall j \in [j' 2^h,(j'+1)2^h - 1],x \in [x' 2^h,(x' + 1) 2^h - 1], j \oplus x > k\)\(j < x\)。那么直接把 \(x\) 那一段区间的 \(f\) 值加到 \(j\) 那一段区间的 \(f\) 值就行了,通过前缀和与差分容易实现。现在总复杂度为 \(O(n V^2)\)

好像优化不了了。我们发现当 \(k\) 比较大的时候,算出来的方案数都等于 \(0\)。所以 \(k\) 的有效上界可能不是 \(V\)。难以发现:\(f(a) \leq \frac{2 \max a_i}{n-1}\)

证明比较抽象。我们发现 \(f(a) \geq 2^k\) 的必要条件是 \(\lfloor \frac{a_i}{2^k} \rfloor\) 两两不同,不然异或出来高位全是 \(0\)。那么就能推出另一个必要条件 \(\max a_i \geq (n-1)2^k\),即 \(2^k \leq \frac{\max a_i}{n-1}\)。我们找到 \(f(a) \in [2^k,2^{k+1})\)\(k\),那么 \(f(a) < 2^{k+1} \leq \frac{2 \max a_i}{n-1}\),即 \(f(a) \leq \frac{2 \max a_i}{n-1}\),那么枚举的 \(>k\)\(k\) 的上限是 \(O(\frac{V}{n})\) 的,所以刚刚看似 \(O(n V^2)\) 的做法其实是 \(O(V^2)\) 的。这样就过了。

技巧:

  • 任意两数异或值的最小值等于排序后相邻数异或值的最小值。
  • 对所有方案求 \(\min\)\(\max\) 的和可以枚举一个 \(>k\) 或者 \(<k\) 的限制,然后转化为全体限制。
  • 形如 \(a \oplus x > k\)\(a \oplus x < k\) 不仅可以字典树,还可以尝试枚举 \(a \oplus x\)\(k\) 最高的不同的位。
  • 时间复杂度不对时可以看看枚举量的范围,可能比想象中的小。
posted @ 2025-12-15 14:31  gevenfeng  阅读(73)  评论(2)    收藏  举报