描述
他有n个信封,n个信件,但是竟然把所有的信都装错了信封!注意了,是全部装错!
现在的问题是:请大家帮可怜的 8006 同学计算一下,一共有多少种可能的错误方式呢?
输入:
输入数据包含多个多个测试实例,每个测试实例占用一行,每行包含一个正
整数 n(1<n<=20),n 表示 8006 的网友的人数。
输出:
对于每行输入请输出可能的错误方式的数量,每个实例的输出占用一行。
样例输入:
2
3
样例输出:
1
2
分析:
这个题,说是递归,其实还是要自己动脑看规律
这题就是个错排公式的裸题:表示有n个物体放在n个位置上,要使得每个物品都放在不同的位置上,有多少种排法。
假设有n个物体,需要求出F(n),则可由前面的F(n-1)及F(n-2)推出。可以这么想:
(1) 前面n-1个位置已经满足条件,每个物品都放在不同的位置上(都是错放了),这也就是F(n-1),然后将最后一个加进来的第n个,与前面任意一个换位置即可。所以这样的个数就是F(n-1)*(n-1);
(2) OK,这样的情况已经搞定了,我们来继续考虑我们所忽视掉的,我们忽视掉了一类就是前面n-1位置个有n-2个满足条件(错放了),有一个在正确的位置上(我们假设这是第K个),这也就是F(n-2),然后将新加入的第n个,与这个K交换位置,即满足了条件每个物品都放在不同的位置上,然后这个K有n-1种(即前面n-1都有可能成为K),所以这种有F(n-2)*(n-1);
综合得到:F(n)=F(n-1)*(n-1)+F(n-2)*(n-1) =》 F(n)=(n-1)*(F(n-1)+F(n-2))这就是错排公式的原型。
#include <iostream>
using namespace std;
long long num[101];
void initialize() {
num[0] = 0;
num[1] = 0;
num[2] = 1;
for (int i = 3; i <= 100; i++) {
num[i] = (i - 1 ) * (num[i-1] + num[i - 2]);
}
}
int main() {
initialize();
int t;
while(cin >> t) {
cout << num[t] << endl;
}
}