UPD on 2024.01.04:换了个图床,望过审。
给定一个长度为 的数组 ,其中 ,试计算满足以下条件的 的排列 的个数:
。
Easy Version 传送门
硬版本跟简单版本的区别就在于,存在 ,也就是对正方形内数字个数不做要求的情况。因此我们仍然可以借用简单版本的思路,将其放到二维平面上思考。
注意到 的 对其他数字的放置不构成任何影响,那么我们只需要考虑 的 即可。对于某个 ,设 为离 最近的 的 (若不存在就设为 )。我们发现此时 不再满足 的限制,且 L 形的宽度不再为 ,因此好像不能借用 Easy Version 的思路分类讨论了。
举个例子,假设 ,我们现在在填 的格子,则有:

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

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

考虑枚举左边的矩形内放了多少个点,不妨设为 个,我们仍然不关心其被放置的具体位置,只需要知道,每放置一个点,右边部分的可用行,也就是纵坐标,就会减少 ,那么我们可以将原问题抽象为在两个矩形内部放置点,例如,假设 ,那么左边的矩形长宽不变,而右边的矩形长度就会减一,那么也就是在一个长宽均为 的矩形(也就是左边的矩形)内部放置一个点,再在一个长为 ,宽为 的矩形(也就是右边的矩形减掉一行)内部放置剩下的一个点。那么我们只需要知道在确定长宽的矩形内放置点的方案数即可。
设矩形的长为 ,宽为 ,需要放置的点数为 ,为了保证没有同一行或者同一列上被放置了超过一个点,就需要先选出 个互不相同的行,方案数为 ,再选出 个互不相同的列,方案数为 ,最后再把这 行与 列两两配对,方案数为 。综上,选点的方案数就为 。
形式化的,对于某一对 ,可以得到,左边的矩形的长宽分别为 ,而右边的矩形长宽就分别为 。设在左边的矩形内选 个点,则右边的矩形的长宽就会变为 。因此,其方案数为:
那么只需要按顺序枚举 将每个 对应的答案垒乘起来即可。由于 ,因此该做法的复杂度也是线性的。
代码
本文作者:forgot-dream
本文链接:https://www.cnblogs.com/forgot-dream/p/17926481.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步