不容易系列之一(错排公式)

描述

他有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;
		}
	
	}
发布了86 篇原创文章 · 获赞 0 · 访问量 3658

猜你喜欢

转载自blog.csdn.net/bijingrui/article/details/104452944