我又双叒叕来水博客辣~


例 1. \(\text{TopCoder - AppleTree}\)

题目大意:数轴上有 \(D\) 个坑,有 \(n\) 棵树要种在这些坑里,限制每棵树与相邻的树的距离至少为 \(r_i\),求种植种数。

\(n,r_i\le 40,D\le 10^5\).

显然枚举排列是不可行的,可以考虑为排列定义一个 "指标" 并分类,若每一类的贡献是相同的,那么就可以用 \((\)贡献 \(\times\) 种类\()\) 的方式来统计答案。

对于此题,定义相邻坑之间的物质为空隙,设 \(X(p)=\sum_{i=1}^{n-1} \max\{r_{p_i},r_{p_{i+1}}\}\). 若排列 \(p\)\(X(p)=k\),就意味着总共 \(D-1\) 个空隙中,有 \(k\) 个空隙不能被使用,即剩下 \(D-1-k\) 个空隙,可以将它们放入 \(n+1\) 个盒子里,那么方案数即为 \(\binom{D-1-k+n}{n}\). 由此观之,\(X(p)\) 可以作为排列的 "指标"。接下来我们只需计算对应指标的排列方案数即可。

在计算 \(X(p)\) 的过程中,取 \(\max\) 是一个非常不方便的操作,所以不妨将 \(r\) 从小到大排序,这样排序后第 \(i\) 棵树无论与谁相邻,增加量总是 \(r_i\).

接下来的操作就比较神了,也应该是排列计数问题的一类通法。考虑维护若干个小排列,它们有相对位置,最后通过不断地加树,形成一个大排列。所以设 \(dp_{i,j,k}\) 为加入前 \(i\) 棵树,形成 \(j\) 个排列,当前 \(X\) 函数之和为 \(k\),就有三种转移:

  • 加入新排列:\(dp_{i+1,j+1,k}\leftarrow (j+1)\cdot dp_{i,j,k}\).
  • 加入之前排列的端点:\(dp_{i+1,j,k+r}\leftarrow 2j\cdot dp_{i,j,k}\).
  • 插入两个排列之间,使它们连通:\(dp_{i+1,j-1,k+2r}\leftarrow (j-1)\cdot dp_{i,j,k}\).

复杂度 \(\mathcal O(1600n^2)\),这是因为 \(X(p)\le 1600\).


例 2. \(\text{[JOI Open 2016] }\)摩天大楼

想到了将数列 \(\{a\}\) 进行排序,但是妹想到可以把贡献 \(a_j-a_i\) 拆分成 \(\sum_{k=i}^{j-1}a_{k+1}-a_k\).

类似上题,将 "指标" 定义为 \(X(p)=\sum|a_{p_i}-a_{p_{i+1}}|\),这题特殊的地方在于,边界的两个小排列的左/右边界不计入贡献。所以设 \(dp_{i,j,k,0/1/2}\) 表示加入前 \(i\) 棵树,形成 \(j\) 个排列,当前 \(X\) 函数之和为 \(k\),边界小排列有 \(0/1/2\) 个。

考虑插入 \(a_{i+1}\),此时 \(X\) 函数的增量是 \(\delta=(a_{i+1}-a_i)\cdot (2j-l)\),这是因为除了 \(1,n\) 两个边界,其它小排列的端点之后添加的相邻的数字都至少有 \(a_{i+1}\). 我们不妨令 \(k'=k+\delta\),那么有如下转移:

  • 新增不在边界的排列:\(dp_{i+1,j+1,k',l}\leftarrow (j+1-l)\cdot dp_{i,j,k,l}\).
  • 新增在边界的排列:\(dp_{i+1,j+1,k',l+1}\leftarrow (2-l)\cdot dp_{i,j,k}\).
  • 加入之前排列的端点:\(dp_{i+1,j,k',l}\leftarrow (2j-l)\cdot dp_{i,j,k}\).
  • 合并两个排列:\(dp_{i+1,j-1,k',l}\leftarrow (j-1)\cdot dp_{i,j,k}\).
  • 另外还有一个非常容易被忽略掉的,将排列和边界连接,这个操作是为了保证边界排列的边界(这里指 \(1,n\) 两个位置)不一定是整个边界排列的最小值:\(dp_{i+1,j,k',l+1}\leftarrow (2-l)\cdot dp_{i,j,k}\).

例 3. \(\text{[CF840C] On the Bench}\)

结论:将能相互构成完全平方数的数字放入一个集合中,则其内部两两数字均能构成完全平方数。反之,不同集合之间的数字一定不能构成完全平方数。

\(d(x)=[\sqrt x\in \mathbb Z]\),则若满足 \(d(ab)=1,d(ac)=1\),就一定满足 \(d(ab\cdot ac)=d(a^2bc)=1\),可以得到 \(d(bc)=1\). 反之,用同样的方法也可以证明,就不再赘述。

于是问题被转化成,给定 \(m\) 个集合,每个集合有 \(r_i\) 个数(题目中这些数 互不相同),且满足 \(n=\sum r_i\). 求有多少种方案排列这 \(n\) 个元素使得相邻元素不在同一集合。

不妨一个一个地考虑集合。设 \(\text{all}=\sum_{j=1}^{i-1}r_j\),现在加入集合 \(i\). 令 \(dp_{i,j}\) 为前 \(i\) 个集合,有 \(j\) 个不合法位置(指此位置上的元素与前一位置元素在同一集合)的方案数。将第 \(i\) 个集合分成 \(k\) 组,那么就会产生 \(r_i-k\) 个不合法位置。现在将这 \(k\) 组在 \(\text{all}+1\) 个位置中挑选 \(k\) 个位置插入:那么还需要枚举这些插入使哪些曾经不合法的位置变得合法,不妨设个数为 \(l\). 那么总转移方程为:

\[dp_{i,j-l+(r_i-k)}\leftarrow (r_i!)\cdot \binom{r_i-1}{k-1}\cdot \binom{j}{l}\cdot \binom{\text{all}+1-j}{k-l}\cdot dp_{i-1,j} \]

复杂度的计算可以先看看代码(有点丑:

for(int i=1;i<=m;++i) {
    for(int j=0; j<=all; ++j) {
        if(!dp[i-1][j]) continue;
        for(int k=1;k<=r[i];++k) for(int l=0; l<=j && l<=k; ++l) {
            inc(dp[i][j-l+r[i]-k],1ll*dp[i-1][j]*C(r[i]-1,k-1)%mod*
                C(j,l)%mod*C(all+1-j,k-l)%mod*fac[r[i]]%mod);
        }
    }
    all += r[i];
}

总复杂度 \(\mathcal O\left( \sum_{i=1}^n \left( \sum_{j=1}^{i-1}r_j \right)\cdot r_i^2 \right)\le \mathcal O\left(\sum_{i=1}^n n\cdot r_i^2\right)\le \mathcal O\left(n\cdot( \sum r_i)^2\right)\le \mathcal O(n^3)\).

(还有一个 \(\mathcal O(n^2)\) 的做法,但我没搞懂那个容斥有点崩溃 qwq


例 4. \(\text{[CF1038E] Maximum Matching}\)

被前面几道题洗脑了……一直在想该如何将新色块插入之前的序列。实际上,由于此题有翻转操作,且要求最大值而非方案数,所以对计数的要求并不苛刻,我们可以用区间 \(\mathtt{dp}\) 来完成这个问题:令 \(dp_{i,j,x,y}\) 为区间 \([i,j]\) 中选出 一个子集,左右颜色分别为 \(x,y\) 的最大值。转移方式有两种:

  • \((i,j]\)\([i,j)\) 继承答案,需要注意颜色可以翻转;
  • 将区间划分成 \([i,k],[k+1,j]\),枚举中转颜色。

例 5. \(\text{[CEOI 2016] kangaroo}\)

首先转化题意:求有多少个长度为 \(n\) 的排列,满足 \(\forall i\in (1,n)\),有 \(p_{i-1}<p_i>p_{i+1}\)\(p_{i-1}>p_i<p_{i+1}\),且保证 \(p_1=s,p_n=t\).

非常巧妙的排列 \(\mathtt{dp}\),考虑从小到大插入数字,只有两种操作:合并两个小排列;插入新排列。对于特殊点 \(s,t\) 特殊考虑即可。


例 6. \(\text{[TopCoder SRM 625] Seatfriends}\)

\(\mathtt{dp}\) 套上环我就会宕机……这题容斥应该是不易的,因为 "最多" 的含义代表过程而不是最终态。所以考虑硬上 \(\mathtt{dp}\).

首先肯定想 \(dp_{i,j}\) 为前 \(i\) 个数形成 \(j\) 个连通块,但这只能处理不包含空位的顺序,处理空位留到下文再谈。由于这是一个环,所以我们 \(\mathtt{dp}\) 出 "块内有序,块间只存在相对位置" 的状态,显然最后需要乘上 \(n\),相当于枚举某个块的开头,这样以相对位置可以唯一确定一种坐座位方案。更准确地说,除了知道相对位置,还需要知道每个块与下一个块之间有多少空位,才能唯一确定坐座位方案。需要注意的是,连通就是空位为零的情况,这和题目状态是有关的,所以空位数需要从 \(1\) 开始枚举。用插板法算出答案为

\[\text{Ans}=n\cdot \sum_{i=1}^k dp_{m,i}\cdot \binom{n-m-1}{i-1} \]

由组合数还可以得知一种特殊情况:\(n=m\). 此时答案并不是 \(dp_{n,1}\),因为这个 \(\mathtt{dp}\) 值默认此连通块开头与末尾之间有空位。真正的答案应该是 \(n\cdot dp_{n,0}\).


posted on 2020-02-24 18:15  Oxide  阅读(390)  评论(0编辑  收藏  举报