最新文章
这里会显示最新的几篇文章摘要。
记录生活,分享知识,与你一起成长。
这里会显示最新的几篇文章摘要。
我们要计算 ( D_n ),即长度为 ( n ) 的排列中,所有元素都不在自己的原位置上的排列个数,这个问题称为错排问题(Derangement)。我们一步一步推导这个公式。
我们需要计算一个排列的数量,其中对于 ( n ) 个数,每个数 ( i ) 都不能出现在位置 ( i ) 上。
例如:
设 ( D_n ) 表示 ( n ) 个数的错排数。
我们考虑第一个数 ( 1 ) 放在哪里:
它不能放在位置 1,所以它可以放在 其他 ( n-1 ) 个位置中的某个位置 ( k )(( 2 \leq k \leq n ))。
现在,原本在位置 ( k ) 的数必须换个位置,我们有两种情况:
因为 ( 1 ) 可以放在任意 ( n-1 ) 个位置上,所以总的递推关系是:
这个递推式是错排问题的核心。
即:
使用递推公式计算几个小的值:
从组合数学的研究中,我们可以推导出错排数的通项公式:
这个公式的直观解释是:我们先算出所有的排列数 ( n! ),然后用容斥原理逐步去掉那些有固定元素在原位的情况。
近似计算:
其中 ( 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) )。
这样,我们就从最基本的思考出发,一步步推导出了错排问题的解法啦!