冷滟泽的个人博客冷滟泽的个人博客

做题总结 1

P4002 [清华集训2017]生成树计数

Tag:Prufer 序列 / 组合计数 / 多项式

我们使用 Prufer 序列来表示一棵树,在原图中的同一连通块中的点标为一种颜色。设第 i 个连通块的大小为 a_i,则在 i,j 两个连通块之间连一条边的贡献是 a_ia_j。设 Prufer 序列中第 i 种颜色出现的次数为 d_i,则贡献为

\frac{(n-2)!}{\prod d_i!}\prod (d_i+1)^ma_i^{d_i+1}\sum(d_i+1)^m

但这样求积与求和混在一起很不好看,考虑将其分拆为每个 d_i 的贡献:

=(n-2)!\prod a_i\sum_{j=1}^{n}\frac{\prod{a_i^{d_i}}}{\prod d_i!}(d_j+1)^{2m}\prod_{i=1,i\neq j}^{n}(d_i+1)^m

发现对于固定的 j,连通块 i 对它的贡献有两种:

\left\{\begin{matrix} \dfrac{a_i^{d_i}}{d_i!}(d_i+1)^m & i\neq j\\ \dfrac{a_i^{d_i}}{d_i!}(d_i+1)^{2m} & i=j\\ \end{matrix}\right.

\sum d_i=n-2 的限制,容易想到使用 OGF,即设:

\begin{gathered} A(x)=\sum_{k\geq 0}\frac{(k+1)^m}{k!} x^{k}\\ B(x)=\sum_{k\geq 0}\frac{(k+1)^{2m}}{k!} x^{k} \end{gathered} \begin{aligned} F(x)=&\sum_{j=1}^{n}B(a_jx)\prod_{i=1,i\neq j}^n A(a_ix)\\ =&\sum_{i=1}^n \frac{B(a_ix)}{A(a_ix)}\prod_{i=1}^n A(a_ix)\\ =&\sum_{i=1}^n \frac{B(a_ix)}{A(a_ix)}\exp\sum_{i=1}^n \ln A(a_ix) \end{aligned}

求出 [x^{n-2}]F(x) 即可得到答案。我们需要求出 \dfrac{B(x)}{A(x)}\ln A(x) 后代入 a_ix 并求和,也就是对第 k 项的系数乘上 a_i^k。我们现在只需要对所有的 k 求出 \sum a_i^k 即可。虽然看似不太能做,但还是有一个奥妙重重的方法能搞定这个问题。

\begin{aligned} G(x)=&\sum_{k\geq 0}\sum_{i} a_i^kx^k=\sum_{i}\frac{1}{1-a_ix}\\ =&\dfrac{\sum_i\prod_{j\neq i}(1-a_jx)}{\prod_i(1-a_ix)} \end{aligned}

设分母为 Q(x),可以分治 FFT 在 O(n\log^2 n) 时间内求出。考虑分母 P(x) 的组合意义,[x^k]P(x) 相当于 n 个物品取 k 个的一个背包,前面枚举了 j 钦定了一个物品不能被选。对于某一种选了 k 个物品方案,会有 kj 不满足条件,所以 [x^k]P(x)=(n-k)[x^k]Q(x)。于是我们可以推出分子。所以这个题就两个 \log 做完了。

P4466 [国家集训队]和与积

Tag:数论分块 / 莫比乌斯反演

直接算 (a,b) 对的个数不太靠谱,考虑除掉同时除掉 d=\gcd(a,b),得到 k_1=a/d, k_2=b/d。问题转化为求满足 k_1d+k_2d\mid k_1k_2d^2(k_1<k_2,\gcd(k_1,k_2)=1,k_2d\leq n)(k_1,k_2,d) 个数。

由整除的线性性可知问题等价于 k_1+k_2\mid k_1k_2d。由

  • \gcd(k,n)k 固定时为积性函数
  • \gcd(a,b)=gcd(a,b-a)

可知 \gcd(k_1+k_2,k_1k_2)=1。也就是说 d 需要满足的条件为 k_1+k_2\mid dk_2d\leq n。容易得出可行的 d 共有 \left\lfloor\dfrac{n}{k_2(k_1+k_2)}\right\rfloor 个。那么答案为

Ans=\sum_{i=1}^{n}\sum_{j=i+1}^n[\gcd(i,j)=1]\left\lfloor\frac{n}{j(i+j)}\right\rfloor

套路地莫反一下,得

\begin{aligned} Ans=&\sum_{d=1}^{n}\mu(d)\sum_{i=1}^{n/d}\sum_{j=i+1}^{n/d}\left\lfloor\frac{n}{d^2j(i+j)}\right\rfloor\\ =&\sum_{d=1}^{n}\mu(d)\sum_{j=2}^{n/d}\sum_{k=j+1}^{2j-1}\left\lfloor\frac{n}{d^2jk}\right\rfloor \end{aligned}

看起来复杂度十分的不对,但实际上这个式子里变量的上界都是十分有限的。d 的实际上界为 \sqrt nj 的实际上界为 \dfrac{\sqrt n}{d},第三维 k 可以直接整除分块。简单积个分可以算出复杂度为 O(n^{3/4})

P5400 [CTS2019]随机立方体

Tag:组合计数

看到「恰好 k 个极大的数」可以首先考虑二项式反演(容斥)。设 f_i 表示存在 k 个极大的数的方案数,则答案为

\sum_i(-1)^{i-k}\binom{i}{k}f_i

那么我们需要求出每个 f_i。根据定义,f_i 可以由三部分组成:

  • 钦定 i 个极大数的位置
  • 与极大数无关的格子任意标号
  • 计算第一步中选出的格子填数的方案数

首先任意两个极大数不可能有一维坐标相等,因为这违反定义。那么有顺序地选出 i 个这样的格子的方案数共有 n^{\underline{i}}m^{\underline{i}}l^{\underline{i}} 种,每选一个格子就少一种选择。与极大数无关的格子就是任意一位坐标都与极大数不同的格子,这样的格子共有 (n-i)(m-i)(l-i) 个,标号方案数为 (nml)^{\underline{(n-i)(m-i)(l-i)}}

最后一步比较麻烦,大概有两种方法计算:第一种是从小到大确定极大数的值,第二种是从大到小。发现最大的极大数是唯一确定的,所以从大到小计算会方便一些。当确定第 j 小的极大数时,应考虑所有只受第 j\sim n 小的极大数约束的格子,一共有 (n-j)+(m-j)+(l-j) 个,可以填的数共有 nml-(n-j)(m-j)(l-j)-1 个,贡献是这两者的一个排列数(下降幂)。把所有 1\leq j\leq i 的贡献乘起来,总方案数为:

[nml-(n-i)(m-i)(l-i)-1]!\prod_{j=1}^{i-1}\frac{1}{nml-(n-j)(m-j)(l-j)}

回代到 f 中即可求得答案。

关于求逆元,一般的做法是带 log 的,可能无法通过。但可以预处理出所有需要的逆元,见 P5431。

P4566 [CTSC2018]青蕈领主

Tag:组合计数 / 多项式

首先根据「连续」的定义,任意两个极大连续段只有包含和并列两种关系,也就是构成了一棵树。那么无解需满足 l_n\neq n 或者无法构成树(可以用栈判断)。设以 i 为根的子树的方案数为 g_i,而 i 的儿子个数为 d_i,那么把每个儿子视为一个元素,则排列后不允许存在除了整个区间以外长度 \geq 2 的连续段。设 f_ii+1 个元素构成的除了整个排列以外不存在长度 \geq 2 的方案数,那么转移就是

g_i=f_{d_i}\prod_{j\in son_i}g_j

因为全都是乘法,所以答案可以写成线性相乘的形式,即

Ans=\prod_{i=1}^{n}f_{d_i}

也就是说,我们只需要求出 f 数组即可。下面给出其递归式:

f_n=\left\{\begin{matrix} 1 & n=0\\ 2 & n=1\\ (n-1)f_{n-1}+\sum_{i=2}^{n-2}(n-i-1)f_if_{n-i} & n\geq 2 \end{matrix}\right.

考虑将一个长度为 n-1 的排列整体加 1 再插入 1 得到出长度为 n 的合法排列,有两种方法:

  • 原排列合法,1 只需不插在 2 旁边即可;
  • 原排列不合法,考虑其逆排列,发现与原排列对应,而 f_n 的意义转化为不存在不包含最大值的长度 \geq 2 的连续段的方案数。那么这个逆排列必须仅有一个不合法的连续段,这里设它的长度为 l。这个区间不能在最左边或者最右边,否则插入 1 以后还是不合法,因此共有 n-l-1 种选法。接下来将 1 与这个区间标号,方案数为 f_l;再将这个区间视为一个元素,与其它元素标号方案数为 f_{n-l}

f_n 是可以使用分治 FFT 计算的,但因为是我 卷 我 自 己,情况会有些不同,需要注意。复杂度 O(n\log^2 n)

P4156 [WC2016]论战捆竹竿

Tag:字符串 / 同余最短路 / DP

假设我们求出了给定字符串的所有周期长度 a_1,a_2,\cdots,a_m,那么答案就是 \sum a_ix_i[0,w-n] 中能取到的值的个数。这是一个经典问题,可以用同余最短路求解,复杂度为 O(m \min a_i),不会的话可以做一下 P3403。

但这题的 m\min a_i 都可以构造到 O(n) 的级别,比如 aaa...b...aaab 放在靠中间的一个位置。这样复杂度就被卡到了 O(n^2)。所以我们需要发掘一下性质。

一个字符串的所有 Border 长度可以被划分成 O(\log n) 个等差数列

这句话的意思不难理解,并且一个 Border 对应了一个周期,划分成等差数列的方案也是对应的。所以怎么证明呢?

考虑设最长 Border 为 A,则所有其他 Border 也是 A 的 Border,分两种情况:

  • |A|\leq n/2,此时考虑串 A 的情况即可。
  • |A|>n/2,它对应的周期长度为 n-|A|,那么长度为 k(n-|A|) 的周期对应的 Border 构成了一个等差数列,并且容易证明其他 Border 的长度都 \leq n/2。于是考虑其他 Border 中最长的一个即可。

这样构造每次会将当前考虑的串长减小至少一半,最多递归 \log n 次,因此命题得证。

所以怎么用到这题上来呢,当然要对每个等差数列分别考虑。比如 x,x+d,\cdots, x+(l-1)d 这个等差数列,我们在模 x 意义下跑同余最短路。发现实际上这就是个模意义下多重背包的问题,最多选 l-1 个物品,这一类的物品体积为 d,选出 k 个的代价为 x+(k-1)d。可以把环拆开看,用单调队列优化即可。

还有一个问题就是不同「物品」的模数都是不同的,如何在不同模数下转换。假设原模数为 lst,当前模数为 cur,则显然 f_i 是可以更新 f_{f_i\bmod cur} 的,这可以直接处理出来。但 f_i 在模 cur 意义下还可以更新 f_{(i+lst)\bmod cur},因此还需要跑一次环上的完全背包(没有 l 的限制),就不需要单调队列了。复杂度 O(Tn\log n)

未经允许不得转载:冷滟泽的个人博客 » 做题总结 1

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址