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

来源:互联网 发布:4g网络优化工程师前景 编辑:程序博客网 时间:2024/05/19 19:56
有个网名叫做8006的男性同学,结交网友无数,最近该同学玩起了浪漫,同时给n个网友每人写了一封信,这都没什么,要命的是,他竟然把所有的信都装错了信封!注意了,是全部装错哟!

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

2


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

错排公式:f(n)=(n-1)(f(n-1)+f(n-2))
经典的信封问题:
一个人写了9封不同的信及相应的9个不同的信封,他把n封信都装错了信封,问都装错信封的装法有多少种?
解题思路:
ABC……表示写着n位友人名字的信封,abc……表示n份相应的写好的信纸。把错装的总数为记作f(n)。假设把a错装进B里了,包含着这个错误的一切错装法分两类:
1b装入A里,这时每种错装的其余部分都与ABab  无关,应有f(n-2)种错装法
2b装入AB之外的一个信封,这时的装信工作实际是把(除a之外的) 信纸bc……装入(除B以外的)n1个信封AC……,显然这时装错的方法f(n-1)种。
总之在a装入B的错误之下,共有错装法f(n-2)+f(n-1)种。a装入C,装入D……n2种错误之下,同样都有f(n-2)+f(n-1)种错装法,因此:
f(n)=(n-1)(f(n-1)+f(n-2))
#include <stdio.h>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;}


0 0