ABC134F Permutation Oddness

[ABC134F] Permutation Oddness

好题,牛牛的一个套路 —— Hanghang

写起来简单,想起来难的一个东西,难点主要是在 状态设置

我们可以把 1N 拆点,于是原题相当于求一个 二分图的完美匹配,并使其 怪异度为 k

我们考虑设置 fi,j,k 三个状态

分别表示 当前考虑了前 i 点,当前有 j 没有匹配上,当前怪异度为 k

显然最终答案就是 fN,0,K

这里可以发现,当前没有匹配上 其实就是 最终匹配上的点不是前 i 对点

我们顺序枚举三个状态,当每次 一个新点加入考虑++i)时,容易发现以下 三种情况

注意,下面 第三维 表示 怪异度 的值 x没有实际意义,且 不代表同一个变量

可以理解成 占位符,关于 怪异度 的部分最后会讨论

  1. 新的点中 一对都都没匹配上

    显然 此时 没匹配上的对数 j 多了一个(新增一对,没有匹配)

    于是我们需要从 fi1,j1,x 处转移

    我们当前只考虑前 i 对点,也就是将 当前没匹配上(实际匹配 i1N)的均看作 一种情况

    两者都没匹配上 的可能 只有一种,这里的贡献应当是 fi1,j1,x

  2. 新的点中 匹配上了一对

    显然 此时 没匹配上的对数 j 不变(新增一对,匹配一对),我们从 fi1,j,x 处转移

    匹配的这一对 有可能是 左部点 Li 匹配到一个 R1Ri1 中未被匹配的右部点,共 j

    也可能是 右部点 Ri 匹配到一个 L1Li1 中未被匹配的左部点,共 j

    还可能是 这一对点 (Li,Ri) 互相匹配,显然一共三种情况,有 2j+1 种可能匹配

    于是这里的贡献应当是 (2j+1)fi1,j,x

  3. 新的点中 匹配上了两对

    显然 此时 没匹配上的对数 j 少了一个(新增一对,匹配两对),我们从 fi1,j+1,x 处转移

    显然 Li 可以找 R1Ri未被匹配的点,共 j+1

    同时 Ri 可以找 L1Li未被匹配的点,共 j+1

    当时想为什么这里是 j+1 而不是 j,挺唐诗的

    我们是从 前 i1 对点,还剩 j+1 对未匹配的 fi1,j+1,x 处转移过来的

    当然有 j+1 种选择,而 fi,j,x 只是表示 当前情况,与 能选择的种数无关

    容易知道,LiRi 的选择 互不干扰,于是最终将产生 (j+1)2可能匹配

    于是这里的贡献应当是 (j+1)2fi1,j+1,x

加在一起,最终的式子就是 fi,j,x=fi1,j1,x+(2j1)fi1,j,x+(j1)2fi1,j+1,x

这时我们来考虑一直忽略的 怪异度 这一维,这里提供一种和 现行题解 不完全相同的理解方式

前面部分参考题解,我们给对 对应点 (Li,Ri) 之间 连线

那么 怪异度 就是 完美匹配跨过连线条数,这里可以参考 Tan_Wei_Ye 的 这篇题解

我们一直只考虑 i 对点的情况,也就是不要把 线 在一开始连完

只当枚举到 i 时,才考虑 Li,Ri 的对应的线 产生的贡献,而此时有 j 没匹配上

换言之就是 L1Li,R1Ri共有 2j 个点 最终 将匹配到 Li+1LN,Ri+1RN

也就是有这 2j 个点 将会跨过 Li,Ri 对应的线,于是产生 2j怪异度

这时就可以 准确地描述 上面的转移了,我们每次一定增加 2j 的怪异度,最终方程如下

根据我们对 怪异度 的理解可以发现,上面的分类讨论 与 此处怪异度的贡献 并无关系

不用担心 上面分类讨论时 忽略怪异度 而对正确性造成影响

fi,j,k=fi1,j1,k2j+(2j+1)fi1,j,k2j+(j+1)2fi1,j+1,k2j

枚举并转移即可,具体见代码

由于我们 怪异度 在转移过程中 不会减少(不会有 fi,j,k 需要用到 fx,y,z  z>k

故我们第三维转移只需要 终止在 需求的 K 即可,不需要转移到 理论怪异度上界 N2

#include <bits/stdc++.h>

const int MAXN = 55;
const int MOD  = 1000000007;

using namespace std;

int F[MAXN][MAXN][MAXN * MAXN];
int N, K;

int main () {
	
	cin >> N >> K, F[0][0][0] = 1;
	
	for (int i = 1; i <= N; ++ i)
		for (int j = 0; j <= i; ++ j)
			for (int k = j * 2; k <= K; ++ k)
				F[i][j][k] = (1ll * ((j << 1) + 1) * F[i - 1][j][k - (j << 1)] + 1ll * (j + 1) * (j + 1) * F[i - 1][j + 1][k - (j << 1)] + (j > 0) * F[i - 1][j - 1][k - (j << 1)]) % MOD;
	
	cout << F[N][0][K] << endl;
	
	return 0;
}
posted @   FAKUMARER  阅读(19)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示