先考虑第一问的答案是什么。考虑对于一个长为 n 的排列,我们对于每个位置 i 求出 fi 表示以 i 结尾的 LIS 长度,gi 为以 i 开头的 LDS 长度。那么我们可以定义一个二元组序列 a,其中 ai=(fi,gi)。
显然 a 序列中的元素互不相同,假设有一对 (i,j) 满足 1≤i<j≤n,那么 pi>pj 能推出 gi>gj,否则能推出 fi<fj。并且根据题目限制,显然有二元组 (x,y) 合法当且仅当 x≤A,y≤B,x+y−1≤C,a 序列中所有元素都应当合法。
那么我们得到了一个 n 的上界 AB−(2A+B−C),我们不妨猜测 n 一定能取到它。后面的过程中将会证明这一点。
考虑任意一个合法二元组 (x,y),如果有 x>1,那么 (x−1,y) 在 a 中的位置 i 一定在 (x,y) 在 a 中的位置 j 之前,且满足 pi<pj。
- 若 i>j,则根据 fi<fj 推出 fj 不能转移到 fi,也就是 pj>pi,这样 gi 就能转移到 gj,与 gi=gj 这一条件矛盾。
- 那么有 i<j,则根据 gi=gj 推出 gj 不能转移到 gi,所以 pi<pj。
同理,如果有 y>1,那么 (x,y−1) 在 a 中的位置 i 一定在 (x,y) 在 a 的位置 j 之后,且满足 pi<pj。
可以发现上述条件是长为 n 的排列 p 合法的充要条件,那么这个排列 p 与两个相同形状的 n 格杨表组成的杨表对 (λ,μ) 构成双射:
- 两个杨表都包含了所有坐标形如 (i,j) 的格子,满足 (i,j) 为一个合法二元组,且这两个杨表中 1∼n 恰好出现一次。
- 对于第一个杨表,有 λi,j<λi,j+1,λi,j<λi+1,j。
- 对于第二个杨表,有 μi,j<μi,j−1,μi,j<μi+1,j。
具体的,从 (λ,μ) 到长为 n 的合法排列 p,使 pμi,j=λi,j 即可;从长为 n 的合法排列 p 到 (λ,μ),求出文章一开始的 f,g,使 λfi,gi=pi,μfi,gi=i 即可。
显然,这样的杨表对一定存在,那么 n 也一定能够取到上界。λ 是标准杨表,它的个数可以用勾长公式直接 O(n+A2) 求出,但是 μ 不是,所以需要另外想办法计数。我们不直接求出 μ 的方案数,而是转而求出等概率随机一个排列填入 μ 使得其合法的概率 P,最后乘上 n! 即可。
考虑另一个杨表 μ′,其中每个数都是 [1,x] 中的整数,且其满足 μi,j′≤μi,j−1′,μi,j′<μi+1,j′。设 μi,j′ 的每个位置都在 [1,x] 中等概率随机时,μ′ 合法的概率为 P′(x),那么有 P=limx→∞P′(x),因为 x→∞ 时,μ′ 中存在相等的两个数的概率为零。
考虑如何计算 P′(x)。令满足 i+j=C+1 的格子所填的数对 i 从小到大分别为 s1,s2,…,sA+B−C,那么我们固定 s 之后就能将合法的 μ′ 与平面上起终点分别为 (S1,T1),(S2,T2),…,(SA,TA) 的 A 条只往右或下走的不交路径组构成双射,具体的,有:
Si=(i,x−A+i)Ti={(B+i,i)(C,si−C+B)i≤C−Bi>C−B
那么根据 LGV 引理,有:
P′(x)=xn∑1≤s1<s2<⋯<sA+B−C≤x∣M∣P=x→∞limxn∑1≤s1<s2<⋯<sA+B−C≤x∣M∣Mi,j={(B+j−ix−A+B)(C−ix−sj−C+B+C−A)j≤C−Bj>C−B
由于我们求的是极值,而分子部分显然是一个多项式,那我们只需要保留最高次项的系数即可:
Mi,j={(B+j−i)!xB+j−i(C−i)!(x−sj−C+B)C−ij≤C−Bj>C−B
观察这个矩阵可以发现它的行列式展开后每一项的次数都是相同的,且恰好是 n−A−B+C 次,那么我们可以上下约掉这么多个 x:
P=x→∞limxA+B−C∑1≤s1<s2<⋯<sA+B−C≤x∣M∣Mi,j={(B+j−i)!1(C−i)!(1−xsj−C+B)C−ij≤C−Bj>C−B
最后,由于 x→∞,所以我们将求和换成积分,将剩余的 x 全都约掉:
P=∫01∫s11⋯∫sA+B−C−11∣M∣dsA+B−C⋯ds2ds1Mi,j={(B+j−i)!1(C−i)!(1−sj−C+B)C−ij≤C−Bj>C−B
把 s 序列反转,值域翻转:
P=∫01∫0s1⋯∫0sA+B−C−1∣M∣dsA+B−C⋯ds2ds1Mi,j={(B+j−i)!1(C−i)!sj−C+BC−ij≤C−Bj>C−B
暴力展开每一项并计算积分的时间复杂度是 O(n+A×A!) 的。事实上,可以通过归纳法证明:
∫01∫0x1⋯∫0xn−1x1a1x2a2⋯xnandxn⋯dx1=k=1∏n∑i=kn(ai+1)1
那么我们对于矩阵 M,按列从右往左扫来状压 DP,设 fS 表示已经选完了后 ∣S∣ 列,并选了 S 中的行的系数之和,每次转移时 ∑(ai+1) 就是已知的。那么我们可以用 O(n+A2A) 的时间复杂度算出 μ 的方案数,将其与 λ 的方案数乘起来即可。总时间复杂度为 O(n+A2+A2A)。