错位排列——杨子曰数学

错位排列——杨子曰数学

超链接:数学合集


首先,什么是错位排列?

就是你有1号物品,2号物品,3号物品……,它们都有自己对应的箱子:1号箱,2号箱,3号箱……

现在你把物品放到箱子里,结果一个物品也没有放对,全部都放错了,那么这个时候这些物品所构成的排列就被称为错位排列

接下来,我们来讨论错位排列怎么求,来简单推导一下错位排列总数的递推

我们用D[i]表示i个物品的错位排列总数

来看看D[n]怎么算,我们现在有n个物品,n个箱子:
在这里插入图片描述
我们来考虑第1个物品,它只要不放到第一个箱子就行,So,有(n-1)种选择

比方说我们把它放到2号箱子
在这里插入图片描述
现在我们来考虑2号物品怎么处理

我们要进行分类讨论了

  1. 2号物品放到1号箱子
    一旦把2号物品放到1号箱子中以后,有没有发现剩下的3~n号物品就是一个新的错位排列了
    在这里插入图片描述
    So,这种情况有D[n-2]种选法

  2. 2号物品不放到1号箱子
    2号物品不能放到1号箱子,那么这时的1号箱子,就相当于问题最开始的2号箱子,都不能装2号物品
    于是你有没有发现,红框里又是一个新的错位排列问题了
    在这里插入图片描述
    那么这种情况就有D[n-1]种选法了

然后1号物品除了放在2号箱子,还可以放在3号,4号……共(n-1)种选择

综上所述, D [ n ] = ( n − 1 ) ∗ ( D [ n − 1 ] + D [ n − 2 ] ) D[n]=(n-1)*(D[n-1]+D[n-2]) D[n]=(n1)(D[n1]+D[n2])


一个小小的递推公式无法满足我们的要求,接下来我们来推导它的通项公式

D [ n ] = ( n − 1 ) ∗ ( D [ n − 1 ] + D [ n − 2 ] ) D[n]=(n-1)*(D[n-1]+D[n-2]) D[n]=(n1)(D[n1]+D[n2])
⟹ D [ n ] ( n − 1 ) ! = D [ n − 1 ] ( n − 2 ) ! + D [ n − 2 ] ( n − 2 ) ! \Longrightarrow\frac{D[n]}{(n-1)!}=\frac{D[n-1]}{(n-2)!}+\frac{D[n-2]}{(n-2)!} (n1)!D[n]=(n2)!D[n1]+(n2)!D[n2]
令 N [ n ] = D [ n ] n !     则 n ∗ N [ n ] = ( n − 1 ) ∗ N [ n − 1 ] + N [ n − 2 ] 令N[n]=\frac{D[n]}{n!}\ \ \ 则n*N[n]=(n-1)*N[n-1]+N[n-2] N[n]=n!D[n]   nN[n]=(n1)N[n1]+N[n2]
⟹ N [ n ] = N [ n − 1 ] − N [ n − 1 ] n + N [ n − 2 ] n \Longrightarrow N[n]=N[n-1]-\frac{N[n-1]}{n}+\frac{N[n-2]}{n} N[n]=N[n1]nN[n1]+nN[n2]
⟹ N [ n ] − N [ n − 1 ] = − 1 n ∗ ( N [ n − 1 ] − N [ n − 2 ] ) \Longrightarrow N[n]-N[n-1]=-\frac{1}{n}*(N[n-1]-N[n-2]) N[n]N[n1]=n1(N[n1]N[n2])
令 H [ n ] = N [ n + 1 ] − N [ n ]     则 H [ n − 1 ] = − 1 n ∗ H [ n − 2 ] 令H[n]=N[n+1]-N[n]\ \ \ 则H[n-1]=-\frac{1}{n}*H[n-2] H[n]=N[n+1]N[n]   H[n1]=n1H[n2]
又 H [ 1 ] = N [ 2 ] − N [ 1 ] = D [ 2 ] 2 − D [ 1 ] 1 = 1 2 又H[1]=N[2]-N[1]=\frac{D[2]}{2}-\frac{D[1]}{1}=\frac{1}{2} H[1]=N[2]N[1]=2D[2]1D[1]=21
⟹ H [ n ] = ( − 1 ) n − 1 ∗ 1 ( n + 1 ) ! \Longrightarrow H[n]=(-1)^{n-1}*\frac{1}{(n+1)!} H[n]=(1)n1(n+1)!1
⟹ N [ n ] − N [ n − 1 ] = H [ n − 1 ] = ( − 1 ) n ∗ 1 n ! \Longrightarrow N[n]-N[n-1]=H[n-1]=(-1)^n*\frac{1}{n!} N[n]N[n1]=H[n1]=(1)nn!1
又 N [ 1 ] = D [ 1 ] 1 = 0 又N[1]=\frac{D[1]}{1}=0 N[1]=1D[1]=0
⟹ N [ n ] = 1 2 ! − 1 3 ! + ⋯ + ( − 1 ) n ∗ 1 n ! \Longrightarrow N[n]=\frac{1}{2!}-\frac{1}{3!}+\cdots+(-1)^n*\frac{1}{n!} N[n]=2!13!1++(1)nn!1
⟹ D [ n ] = n ! ∗ ( 1 2 ! − 1 3 ! + ⋯ + ( − 1 ) n ∗ 1 n ! ) \Longrightarrow D[n]=n!*(\frac{1}{2!}-\frac{1}{3!}+\cdots+(-1)^n*\frac{1}{n!}) D[n]=n!(2!13!1++(1)nn!1)

OK,完事

参考:
https://bubbleioa.blog.luogu.org/solution-p4071

于HG机房

<think>嗯,用户想了解错位排列的递推公式以及如何用算法实现。首先,我需要回忆一下错位排列的定义和递推公式。根据引用中的信息,欧拉给出了递推公式,f(n) = (n-1)*(f(n-1) + f(n-2)),对吧?那这个公式的推导过程是怎样的呢?比如,当新增第n个元素时,它不能放在第n位,所以有n-1种选择。假设它放在第i位,那么分两种情况:原来的第i个元素放到第n位,剩下的n-2个元素错位排列,也就是f(n-2);或者原来的第i个元素不放到第n位,那么剩下的n-1个元素需要错位排列,即f(n-1)。这样两种情况相加,再乘以n-1种选择,得到递推式。 接下来,用户可能需要具体的算法实现。引用中的代码示例使用了动态规划的方法,初始化a[2]=1,a[3]=2,然后循环计算到n。要注意处理n=0或1的情况,返回0,对吗?比如当n=1时,没有错位排列的可能,所以结果为0。而n=2时,只有一种可能,交换两个元素。 用户可能还关心时间复杂度和空间复杂度。动态规划的方法时间复杂度是O(n),空间复杂度也是O(n),但如果只需要计算到某个n的值,可以优化空间,只保留前两个状态,这样空间复杂度变成O(1)。不过引用中的代码似乎用了数组来存储所有中间结果,可能更适合多次查询的情况,比如预处理后直接查表。 然后,用户的应用场景可能涉及组合数学问题,比如信封装错或者排列问题中的约束条件。编程实现时需要注意大数问题,因为当n较大时,结果会迅速增长,可能需要使用大整数类型,如Python中的int可以自动处理,而C++中可能需要使用long long或者高精度库。 另外,用户可能对递推公式的数学证明感兴趣,或者如何从排列组合的角度理解这个递推关系。比如,可以通过数学归纳法来证明递推公式的正确性,或者举例说明n=4时的情况,如引用中给出的输出9,验证递推的正确性。 最后,需要确保代码示例正确,比如在Python中实现递推公式,处理边界条件,并测试几个例子,如n=4返回9,n=5返回44等。可能还需要对比递归和动态规划实现的效率,因为递归会有重复计算,而动态规划更高效。</think>### 错位排列递推公式与算法实现 #### 一、递推公式推导 错位排列(全错位排列)指长度为$n$的排列中,**所有元素都不在原始位置**的情况总数,记为$f(n)$。数学家欧拉给出的递推公式为: $$f(n) = (n-1) \cdot [f(n-1) + f(n-2)]$$ 其中初始条件为: - $f(0)=1$(空排列视为有效) - $f(1)=0$(单个元素无法错位) - $f(2)=1$(仅1种交换方式) **推导过程**: 1. 新增第$n$个元素时,该元素不能放在第$n$位,因此有$n-1$种位置选择(假设放在第$i$位) 2. 此时原第$i$位的元素有两种情况: - **情况1**:原第$i$位元素放在第$n$位 → 剩余$n-2$个元素错位排列,共$f(n-2)$种 - **情况2**:原第$i$位元素不放在第$n$位 → 剩余$n-1$个元素错位排列,共$f(n-1)$种 3. 综合两种情况,总数为$(n-1) \cdot [f(n-1)+f(n-2)]$[^1] #### 二、算法实现 ##### 动态规划法(时间复杂度$O(n)$,空间复杂度$O(n)$) ```python def derangement(n): if n == 0: return 1 dp = [0] * (n+1) dp[0], dp[1], dp[2] = 1, 0, 1 for i in range(3, n+1): dp[i] = (i-1) * (dp[i-1] + dp[i-2]) return dp[n] ``` ##### 空间优化版(空间复杂度$O(1)$) ```python def derangement_optimized(n): if n == 0: return 1 if n == 1: return 0 a, b = 0, 1 # f(1), f(2) for i in range(3, n+1): a, b = b, (i-1)*(a + b) return b ``` #### 三、应用场景 1. **密码学**:生成无固定位置的置换表 2. **组合数学**:信封错装问题、随机排列生成 3. **算法设计**:随机化算法中的位置扰动 4. **数据分析**:检验数据分布的随机性 #### 四、验证示例 ```python print(derangement(4)) # 输出9 print(derangement(5)) # 输出44 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值