错排公式推导

我们要计算 ( D_n ),即长度为 ( n ) 的排列中,所有元素都不在自己的原位置上的排列个数,这个问题称为错排问题(Derangement)。我们一步一步推导这个公式。


第一步:理解问题

我们需要计算一个排列的数量,其中对于 ( n ) 个数,每个数 ( i ) 都不能出现在位置 ( i ) 上。

例如:

  • 对于 ( n = 3 ),所有排列是:

    (1,2,3),(1,3,2),(2,1,3),(2,3,1),(3,1,2),(3,2,1)

    只有 ( (2,3,1) ) 和 ( (3,1,2) ) 满足错排条件,所以 ( D_3 = 2 )。

第二步:递归思想

设 ( D_n ) 表示 ( n ) 个数的错排数。

我们考虑第一个数 ( 1 ) 放在哪里:

  • 它不能放在位置 1,所以它可以放在 其他 ( n-1 ) 个位置中的某个位置 ( k )(( 2 \leq k \leq n ))。

  • 现在,原本在位置 ( k ) 的数必须换个位置,我们有两种情况:

    1. 把它放回位置 1:这样剩下的 ( n-1 ) 个数要构成一个错排,即剩下的 ( n-1 ) 个数的错排问题,方案数是 ( D_{n-2} )。
    2. 不放回位置 1:那么它仍然是一个错排问题,只不过规模是 ( n-1 ),方案数是 ( D_{n-1} )。

因为 ( 1 ) 可以放在任意 ( n-1 ) 个位置上,所以总的递推关系是:

Dn=(n1)×(Dn1+Dn2)

这个递推式是错排问题的核心。


第三步:边界条件

  • 只有 1 个数时,没有错排,( D_1 = 0 )。
  • 有 2 个数时,唯一的错排是 ( (2,1) ),所以 ( D_2 = 1 )。

即:

D1=0,D2=1


第四步:具体计算

使用递推公式计算几个小的值:

D3=(31)×(D2+D1)=2×(1+0)=2

D4=(41)×(D3+D2)=3×(2+1)=6

D5=(51)×(D4+D3)=4×(6+2)=32


第五步:一般公式

从组合数学的研究中,我们可以推导出错排数的通项公式:

Dn=n!i=0n(1)ii!

这个公式的直观解释是:我们先算出所有的排列数 ( n! ),然后用容斥原理逐步去掉那些有固定元素在原位的情况。

近似计算:

Dnn!e

其中 ( e ) 是自然对数的底(约等于 2.718)。


第六步:代码实现

递归方式

#include <iostream>
using namespace std;

long long derangement(int n) {
    if (n == 1) return 0;
    if (n == 2) return 1;
    return (n - 1) * (derangement(n - 1) + derangement(n - 2));
}

int main() {
    int n;
    cin >> n;
    cout << derangement(n) << endl;
    return 0;
}

动态规划方式

#include <iostream>
using namespace std;

long long dp[1000005];

int main() {
    int n;
    cin >> n;
    
    dp[1] = 0;
    dp[2] = 1;
    
    for (int i = 3; i <= n; ++i) {
        dp[i] = (i - 1) * (dp[i - 1] + dp[i - 2]);
    }
    
    cout << dp[n] << endl;
    return 0;
}

时间复杂度:( O(n) ),空间复杂度:( O(n) )。


总结

  1. 递推关系是:

    Dn=(n1)×(Dn1+Dn2)

  2. 边界条件是:

    D1=0,D2=1

  3. 计算公式:

    Dn=n!i=0n(1)ii!

  4. 代码可以用递归或者动态规划来求解。

这样,我们就从最基本的思考出发,一步步推导出了错排问题的解法啦!

posted @   bakul  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示