HDU 1465 不容易系列之一【错排】

有个网名叫做8006的男性同学,结交网友无数,最近该同学玩起了浪漫,同时给n个网友每人写了一封信,这都没什么,要命的是,他竟然把所有的信都装错了信封!注意了,是全部装错哟!

现在的问题是:请帮可怜的8006同学计算一下,一共有多少种可能的错误方式呢?
 
Input
输入数据包含多个多个测试实例,每个测试实例占用一行,每行包含一个正整数n(1
 
Output
对于每行输入请输出可能的错误方式的数量,每个实例的输出占用一行。
 
Sample Input
2
3
 
Sample Output
1

2


装信封问题是典型的错排问题

错排公式: f(n)=(n-1)(f(n-1)+f(n-2))
经典的信封问题:
一个人写了 9 封不同的信及相应的 9 个不同的信封,他把 n 封信都装错了信封,问都装错信封的装法有多少种?
解题思路:
A B C …… 表示写着 n 位友人名字的信封, a b c …… 表示 n 份相应的写 好的信纸。把错装的总数为记作 f(n) 。假设把 a 错装进 B 里了,包含着这个错误 的一切错装法分两类:
1 b 装入 A 里,这时每种错装的其余部分都与 A B a b    无关,应有 f(n-2) 种错装法
2 b 装入 A B 之外的一个信封,这时的装信工作实际是把(除 a 之外的)  信纸 b c …… 装入(除 B 以外的) n 1 个信封 A C …… ,显然这时装错的方法 f(n-1) 种。
总之在 a 装入 B 的错误之下,共有错装法 f(n-2)+f(n-1) 种。 a 装入 C ,装入 D…… n 2 种错误之下,同样都有 f(n-2)+f(n-1) 种错装法,因此 :
f(n)=(n-1) ( f(n-1)+f(n-2) )
#include 
int main()
{
	int n,i;
	__int64 a[21];
	a[1]=0;
	a[2]=1;
	for(i=3;i<21;i++)
		a[i]=(i-1)*(a[i-1]+a[i-2]);
	while( scanf("%d",&n) != EOF)
	printf("%I64d\n",a[n]);
	return 0;
}


你可能感兴趣的:(数论)