杭电1465
题意:向n个人发n封信,全部都发错的情况有多少种
Analyse:
记错排的符号为f(n),则f(n)=A(n,n)-C(n,1)*f(n-1)-C(n,2)*f(n-2)……-C(n,n-2)*f(2)-1(表示n个元素的全排列排除有k(1<=k<=n-2)个放对位置的情况,不存在n-1个放对位置的情况,最后的1表示全部放对的情况),有f(n-1)=A(n-1,n-1)-C(n-1,1)*f(n-2)-C(n-1,2)*f(n-3)……-C(n-1,n-3)*f(2)-1,将f(n-1)代入到f(n)得到,f(n)=C(n,2)*f(n-2)+2*C(n,3)*f(n-3)+……+(n-3)*C(n,n-2)*f(2)+n-1。
View Code
1 #include<stdio.h>
2 __int64 c[21][21];
3 main()
4 {
5 __int64 awnum[21]={0,0,1,2};//全错的情况
6 int i,j;
7 int n;
8 //构建杨辉三角
9 c[0][0]=1;
10 for(i=1;i<=20;i++)
11 {
12 c[i][0]=1;
13 c[i][i]=1;
14 for(j=1;j<i;j++)
15 c[i][j]=c[i-1][j-1]+c[i-1][j];
16 }
17 //递推出各种全错数目
18 for(i=4;i<=20;i++)
19 {
20 awnum[i]=i-1;
21 for(j=i-2;j>=2;j--)
22 awnum[i]+=(i-j-1)*c[i][i-j]*awnum[j];
23 }
24 while(scanf("%d",&n)==1)
25 printf("%I64d\n",awnum[n]);
26 }
后来知道错排有递推公式,f(n)=(n-1)*(f(n-1)+f(n-2)),f(1)=0,f(2)=1。解释如下:
先将第一个位置的元素放到第k个位置(对k的选择有(n-1)种情况);然后第k个位置的元素如果放在第一个位置,则有f(n-2)种情况,而第k个位置的元素若不放在第一个位置,则将第一个位置看成是k原本的位置(因为k不放在第一个位置),因此相当于n-1个元素的错排,有f(n-1)种情况。由加法原理和乘法原理可得上述公式。