错排公式的递推形式
推导过程
想要推导复杂的公式,我们不妨由浅入深从个数少的情况开始分析
我们假设有n个字母需要错排,错排总数为sum
当n=1时,因为没有错排的可能,所有sum=0
当n=2时,只存在将两个字母互换的一种情况,sum=1
当n=3时
假设三个字母为ABC
通过列举可知有以下可能
BCA,CAB
共有两种,sum=2
当n=4时
假设四个字母为A B C D
首先,挑选BCD其中一个字母插入 A 的位置,共有三种可能
假设这个字母是B,可暂时写为 B A C D
此时A与B的位置已错开,只需对CD进行错排同n=2的情况
CD错排的情况分析完后,A就不能继续留在2号位置
此时单独对ACD分析可知,A不能留在2号位,C不能留在3号位,D不能留在4号位,便可将ACD转化成三个字母错排的情况,即n=3的情况
因此sum=3 *(2 + 1)= 9
根据推导过程的思路可得公式
s
u
m
=
(
n
−
1
)
∗
(
a
[
n
−
1
]
+
a
[
n
−
2
]
)
sum = (n - 1) * (a[n - 1] + a[n - 2])
sum=(n−1)∗(a[n−1]+a[n−2])
既然得到了公式,为了验证它的正确性可以对n=5时进行验证
ABCDE先将AB互换变为BACDE,再对CDE进行n=3的错排,再对ACDE进行n=4的错排,可以发现思路不仅与上述公式相同,答案也与数学知识推出的相同(均为44)
本题详解
#include<bits/stdc++.h>
using namespace std;
#define int long long //宏定义,将int类型改为long long类型
const int N = 10010;
int a[N];
signed main() //宏定义后,需要写成signed main
{
int n;
cin >> n;
a[1] = 0;
a[2] = 1;
for (int i = 3; i <= n; i ++)
a[i] = (a[i - 1] + a[i - 2]) * (i - 1); //错排公式求错排总数
cout << a[n] << endl;
return 0;
}