You don't need to call me now you're gone.|

ForgotDream

园龄:2年4个月粉丝:12关注:47

CF1909F2 Small Permutation Problem (Hard Version)

UPD on 2024.01.04:换了个图床,望过审。

给定一个长度为 n 的数组 a,其中 ai[1,n],试计算满足以下条件的 [1,n] 的排列 p 的个数:

  • i[1,n],有 1ji[pji]=ai 或 ai=1

n2×105

Easy Version 传送门

硬版本跟简单版本的区别就在于,存在 ai=1,也就是对正方形内数字个数不做要求的情况。因此我们仍然可以借用简单版本的思路,将其放到二维平面上思考。

注意到 ai=1i 对其他数字的放置不构成任何影响,那么我们只需要考虑 ai1i 即可。对于某个 i,设 j<i 为离 i 最近的 aj1j(若不存在就设为 0)。我们发现此时 d=aiaj 不再满足 d{0,1,2} 的限制,且 L 形的宽度不再为 1,因此好像不能借用 Easy Version 的思路分类讨论了。

举个例子,假设 a4=2,a5=1,a6=5,我们现在在填 i=6 的格子,则有:

此时 L 形的宽度为 2,且需要在 i,pi4 的区域放置两个点,那么我们很容易知道会有两行与两列的点受到影响。我们不关心具体是哪两行两列无法放置点,因此不失一般性的,我们假设是 1,2 这两行两列无法放置。那么就有:

只有图中红色的部分是可用的。进一步的,我们将红色的部分划分为两个区域:

考虑枚举左边的矩形内放了多少个点,不妨设为 k 个,我们仍然不关心其被放置的具体位置,只需要知道,每放置一个点,右边部分的可用行,也就是纵坐标,就会减少 1,那么我们可以将原问题抽象为在两个矩形内部放置点,例如,假设 k=1,那么左边的矩形长宽不变,而右边的矩形长度就会减一,那么也就是在一个长宽均为 2 的矩形(也就是左边的矩形)内部放置一个点,再在一个长为 3,宽为 2 的矩形(也就是右边的矩形减掉一行)内部放置剩下的一个点。那么我们只需要知道在确定长宽的矩形内放置点的方案数即可。

设矩形的长为 h,宽为 w,需要放置的点数为 k,为了保证没有同一行或者同一列上被放置了超过一个点,就需要先选出 k 个互不相同的行,方案数为 (wk),再选出 k 个互不相同的列,方案数为 (hk),最后再把这 k 行与 k 列两两配对,方案数为 k!。综上,选点的方案数就为 (hk)(wk)k!

形式化的,对于某一对 i,j,可以得到,左边的矩形的长宽分别为 ij,jaj,而右边的矩形长宽就分别为 ij,iaj。设在左边的矩形内选 k 个点,则右边的矩形的长宽就会变为 ij,iajk。因此,其方案数为:

0kd((ijk)(jajk)k!)((ijdk)(iajkdk)(dk)!)

那么只需要按顺序枚举 i 将每个 i 对应的答案垒乘起来即可。由于 d=ana1=O(n),因此该做法的复杂度也是线性的。

代码

本文作者:forgot-dream

本文链接:https://www.cnblogs.com/forgot-dream/p/17926481.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   ForgotDream  阅读(71)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起