UVa 12887 The Soldier‘s Dilemma

题目描述

NNN 名士兵,身高各不相同,他们排成一排。
指挥官会任意选出三名士兵出列,其他士兵离开,只留下这三名士兵。
如果从左到右这三名士兵的身高顺序是 短、高、中(即最矮、最高、中等),那么指挥官会生气并惩罚他们。
其他任何顺序(如高、中、短;中、短、高等)都不会被惩罚。
士兵们不想被惩罚。
问:有多少种排列方式,使得无论选择哪三名士兵,他们从左到右的顺序 永远不会 出现“短、高、中”?

输入格式

第一行一个整数 TTT1≤T≤5001 \le T \le 5001T500),表示测试用例数量。
接下来 TTT 行,每行一个整数 NNN1≤N≤50001 \le N \le 50001N5000)。

输出格式

对于每个测试用例,输出满足条件的排列数,结果对 109+710^9+7109+7 取模。

样例输入

2
2
3

样例输出

2
5

问题分析

1. 问题重述

我们有 NNN 个不同的身高,不妨用 1,2,…,N1, 2, \dots, N1,2,,N 表示,数值越小越矮。
一个排列 π\piπ 表示士兵从左到右的排列顺序。

任意选出三个位置 i<j<ki < j < ki<j<k,设这三个人的身高为 x=πix = \pi_ix=πiy=πjy = \pi_jy=πjz=πkz = \pi_kz=πk
将这三个身高按数值从小到大排序,得到 a<b<ca < b < ca<b<c,分别对应“短”、“中”、“高”。
禁止的情况是:在原排列中,这三个人的出现顺序是 ,即:

  • 最矮的人 aaa 在位置 iii
  • 最高的人 ccc 在位置 jjj
  • 中等的人 bbb 在位置 kkk

因为 a<b<ca < b < ca<b<c,所以 pi<pk<pjp_i < p_k < p_jpi<pk<pj

2. 转换为模式避免问题

在排列模式避免(Pattern Avoidance\texttt{Pattern Avoidance}Pattern Avoidance)理论中,三个位置 i<j<ki < j < ki<j<k 满足 pi<pk<pjp_i < p_k < p_jpi<pk<pj 被称为 1−3−21-3-2132 模式(也称为 132132132 模式)。

因此,本题等价于:求长度为 NNN 且不包含 132132132 模式的排列个数

这是一个经典结论:避免 132132132 模式的排列数等于第 NNN 个卡特兰数(Catalan Number\texttt{Catalan Number}Catalan Number


解题思路

3. 卡特兰数简介

卡特兰数 CnC_nCn 的定义为:

C0=1,Cn+1=∑i=0nCi⋅Cn−i C_0 = 1, \quad C_{n+1} = \sum_{i=0}^{n} C_i \cdot C_{n-i} C0=1,Cn+1=i=0nCiCni

通项公式为:

Cn=1n+1(2nn) C_n = \frac{1}{n+1} \binom{2n}{n} Cn=n+11(n2n)

卡特兰数在很多组合问题中出现,例如:

  • 合法括号序列数
  • 二叉树形态数
  • 凸多边形三角剖分数
  • 不越过对角线的格路路径数
  • 避免 132132132 模式的排列数

4. 为什么答案是卡特兰数?

这里给出一种直观理解(不严格证明,但有助于记忆):

考虑排列中最大值 NNN 的位置。如果最大值在位置 kkk,那么它左边有 k−1k-1k1 个数,右边有 N−kN-kNk 个数。
因为最大值不能出现在 132 模式中作为“高”的角色,实际上通过递推分析可以得到:

f(n)f(n)f(n) 为长度为 nnn 的合法排列数。考虑最大值的位置,其左边和右边的排列必须各自避免 132132132 模式,且右边所有数必须大于左边所有数(否则会出现 132132132 模式)。
这恰好满足卡特兰数的递推关系:

f(n)=∑i=0n−1f(i)⋅f(n−1−i) f(n) = \sum_{i=0}^{n-1} f(i) \cdot f(n-1-i) f(n)=i=0n1f(i)f(n1i)

与卡特兰数递推一致,且 f(0)=1f(0)=1f(0)=1,因此 f(n)=Cnf(n) = C_nf(n)=Cn

5. 模运算与预处理

由于 N≤5000N \le 5000N5000,我们需要计算 CN=1N+1(2NN) mod MC_N = \frac{1}{N+1} \binom{2N}{N} \bmod MCN=N+11(N2N)modM,其中 M=109+7M = 10^9+7M=109+7

  • 预处理阶乘 fact[i] = i! mod M,最大到 2N2N2N
  • 预处理逆元 invFact[i],使用费马小定理 a−1≡aM−2(modM)a^{-1} \equiv a^{M-2} \pmod{M}a1aM2(modM)
  • 组合数 (2NN)=fact[2N]⋅invFact[N]⋅invFact[N] mod M\binom{2N}{N} = fact[2N] \cdot invFact[N] \cdot invFact[N] \bmod M(N2N)=fact[2N]invFact[N]invFact[N]modM
  • 最后乘以 N+1N+1N+1 的逆元。

时间复杂度 O(Nmax⁡+T)O(N_{\max} + T)O(Nmax+T),空间复杂度 O(Nmax⁡)O(N_{\max})O(Nmax)


代码实现

// The Soldier's Dilemma
// UVa ID: 12887
// Verdict: Accepted
// Submission Date: 2026-05-27
// UVa Run Time: 0.000s
//
// 版权所有(C)2026,邱秋。metaphysis # yeah dot net

#include <bits/stdc++.h>
using namespace std;

const int MOD = 1000000007;
const int MAXN = 5000;

long long fact[MAXN * 2 + 5], invFact[MAXN * 2 + 5];

long long modPow(long long a, long long e) {
    long long res = 1;
    while (e) {
        if (e & 1) res = res * a % MOD;
        a = a * a % MOD;
        e >>= 1;
    }
    return res;
}

void precompute() {
    fact[0] = 1;
    for (int i = 1; i <= 2 * MAXN; ++i)
        fact[i] = fact[i - 1] * i % MOD;
    invFact[2 * MAXN] = modPow(fact[2 * MAXN], MOD - 2);
    for (int i = 2 * MAXN - 1; i >= 0; --i)
        invFact[i] = invFact[i + 1] * (i + 1) % MOD;
}

long long comb(int n, int k) {
    if (k < 0 || k > n) return 0;
    return fact[n] * invFact[k] % MOD * invFact[n - k] % MOD;
}

long long catalan(int n) {
    return comb(2 * n, n) * modPow(n + 1, MOD - 2) % MOD;
}

int main() {
    precompute();
    int T;
    scanf("%d", &T);
    while (T--) {
        int N;
        scanf("%d", &N);
        printf("%lld\n", catalan(N));
    }
    return 0;
}

总结

本题的关键在于将“短、高、中”这种身高顺序转化为排列中的 132132132 模式,然后利用组合数学中的经典结论:避免 132132132 模式的排列数等于卡特兰数。
通过预处理阶乘和逆元,可以在 O(1)O(1)O(1) 时间内回答每个测试用例,总时间复杂度 O(Nmax⁡+T)O(N_{\max} + T)O(Nmax+T),空间复杂度 O(Nmax⁡)O(N_{\max})O(Nmax),完全满足题目限制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值