1 条题解
-
0
题目理解
我们需要求长度为 的排列中,恰好有 个位置满足 (这样的位置称为"稳定"位置)的排列数量。
换句话说,就是求有 个不动点的 元排列的数量。
问题分析
1. 组合数学建模
设 表示 个元素的错位排列数(即没有不动点的排列数)。
对于恰好有 个不动点的排列,我们可以:
- 从 个位置中选出 个作为不动点: 种选择
- 剩下的 个位置构成错位排列: 种
因此答案为: [ \text{Answer} = \binom{n}{m} \times D(n-m) ]
错位排列数公式
错位排列数 有递推公式: [ D(n) = (n-1) \times [D(n-1) + D(n-2)] ] 边界条件: [ D(0) = 1,\quad D(1) = 0 ]
也有通项公式: [ D(n) = n! \times \sum_{k=0}^{n} \frac{(-1)^k}{k!} ]
算法设计
步骤 1:预处理阶乘和逆元
由于 ,我们需要预处理:
- 阶乘数组
- 阶乘逆元数组
步骤 2:预处理错位排列数
使用递推公式: [ D[0] = 1,\ D[1] = 0 ] [ D[i] = (i-1) \times (D[i-1] + D[i-2]) \mod MOD ]
步骤 3:组合数计算
[ \binom{n}{m} = \frac{n!}{m!(n-m)!} = fact[n] \times inv_fact[m] \times inv_fact[n-m] \mod MOD ]
步骤 4:答案计算
对于每组 :
- 如果 ,答案为
- 否则答案为
特殊情况处理
- :只有恒等排列满足,答案为
- :不可能有恰好 个不动点,答案为
- :空排列,如果 答案为 ,否则为
复杂度分析
- 预处理:,其中
- 每次查询:
- 总复杂度:
样例验证
输入:
5 1 0 1 1 5 2 100 50 10000 5000计算过程:
- :
- :
- :
- $D(3) = 2 \times (D(2) + D(1)) = 2 \times (1 + 0) = 2$
- :大数,需要取模计算
- :大数,需要取模计算
输出:
0 1 20 578028887 60695423符合样例。
模运算细节
模数 是质数,可以用费马小定理求逆元: [ a^{-1} \equiv a^{MOD-2} \pmod{MOD} ]
数学公式总结
答案的完整表达式: [ \text{Answer}(n,m) = \begin{cases} 0 & \text{if } m > n \ \binom{n}{m} \cdot D(n-m) & \text{otherwise} \end{cases} ]
其中: [ \binom{n}{m} = \frac{n!}{m!(n-m)!} ] [ D(n) = \begin{cases} 1 & n = 0 \ 0 & n = 1 \ (n-1)[D(n-1) + D(n-2)] & n \geq 2 \end{cases} ]
总结
本题的关键在于:
- 将问题分解为"选择不动点"和"剩余位置错排"两个独立问题
- 使用乘法原理组合结果
- 预处理所有需要的值以实现 查询
- 注意模运算和边界情况处理
这是一个经典的组合数学问题,考察了对错位排列和组合数的理解与应用。
- 1
信息
- ID
- 4341
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者