[题解][ARC167C]一道申必的数数题

发布时间 2023-10-31 16:27:03作者: ajthreac

这道题目千岩万转,需要用到多次转化,其中有一些转化较为常见,有一些则需要思考。

首先观察原问题:给定数列 \(a\),对于所有 \(1\sim n\) 的排列 \(p\),构建一张只有 \(j-i\le k\)\((i,j)\) 之间有权值为 \(\max\{a_{p_i}, a_{p_j}\}\) 的边的图,求所有图的最小生成树边权和。

由于他都列出所有排列了,那么 \(a\) 如何就无所谓了,我们可以直接排序,排序的好处是能把 \(\max\) 挪到下标上。这样题目就变成了:给定数列 \(a\),对于所有 \(1\sim n\) 的排列 \(p\),构建一张只有 \(j-i\le k\)\((i,j)\) 之间有权值为 \(a_{\max\{p_i, p_j\}}\) 的边的图,求所有图的最小生成树边权和。

接下来看到边权和,应当第一时间想到计算每个权值的贡献,我们记 \(a_i\) 这个权值在所有图中出现了 \(g_i\) 次,那么答案就是 \(\sum a_ig_i\)。根据最小生成树的 Kruskal 求解方式,此时计算已经和数列 \(a\) 无关了,只和 \(a\) 内大小关系有关,我们应当从小到大选择不成环的边加入生成树。

目前仍然是不可做的,继续尝试转化,常见的技巧是令 \(g_i=f_i-f_{i-1}\),其中 \(f_i\) 表示 \(a_1\)\(a_i\) 这些权值出现的总次数。这样我们就可以聚焦于求解 \(f(x)\)对于所有 \(1\sim n\) 的排列 \(p\),构建一张只有 \(j-i\le k\)\(\max\{p_i, p_j\}\le x\)\((i,j)\) 之间有边的图,求在所有图中从小到大选不成环的边能选出来的总数。

接下来再找能转化的条件,我们不能白把 \(\max\) 扔进下标,显然此时只有 \(p_i\le x\) 的点才能连边。这时候要时刻提醒自己 \(p\) 是个排列,所以这样的点拿出来一共有 \(x\) 个,他们之间可以随便连边,这也印证了前面 \(g\) 的转化是正确的,否则就无法随便连边。这样要求就只剩下了不成环下标差 \(\le k\) 两个条件了。

假设现在给定了排列 \(p\),那么这 \(x\) 个点就可以确定,考虑如何连边最优。由于跟下标有关,我们就假设拿出来的这些点下标是递增的,那么显然应当尽量在相邻点之间连,可以证明如果连的不是相邻点,可以修改得更不劣。所以接下来的问题就变成了:对于所有 \(1\sim n\) 的排列 \(p\),从 \(p\) 中拿出所有 \(p_i\le x\) 的数构成新数列 \(q\),求满足 \(q_{i+1}-q_i\le k\) 的间隔个数。

此时我们只剩下所有排列需要杀了,这仍然应当让你想到计算贡献。对于每个间隔,我们分别计算他的贡献,显然间隔之间是无关的,应当先计算某一个间隔的答案。我们不妨钦定这两个相邻的数差 \(k'\),最后只需要对 \(1\sim k\)\(k'\) 求和就好了。此时我们不用管其他位置,他们会在钦定别人时被算上,可以任意填充。由于钦定了这两个差 \(k'\) 的数,那么就相当于从剩下的下标里面选数,这时方案为 \(\dbinom{n-k'-1}{x-2}\) 种。而这两个差 \(k'\) 的数在原数列中位置共有 \(n-k'\) 种,所以总共的方案数是 \((x-1)\sum_{k'=1}^k \dbinom{n-k'}{x-1}\)。再加上排列的部分,\(\le x\) 的部分排一下,\(>x\) 的部分排一下,答案就再乘上一个 \(x!(n-x)!\)

到此,我们解决了这道题目。

排序、算贡献、做差、贪心、算贡献,虽然弯弯绕绕,但每一步都有迹可循,是数数题中比较锻炼综合能力的。