错排问题
一个寝室有四个人,过节时,每个人都会送出一封贺卡,假如一个盒子里有四封贺卡,寝室的每个成员都要拿出一封,但是肯定不能拿自己写的贺卡,如果每个人拿到的是别人送的贺卡,问这种情况有多少种?
这就是典型的错排问题。
先给出公式:f(n) = (n-1)*(f(n-1) + f(n-2)).
分两步:
第一步:第一个人的贺卡放到2,3,4中的一个,此时有n-1种情况。
第二步:接到第一步,假如第一个人的贺卡放到了位置k(k当然不等于1了),那么先处理这第k个位置的贺卡,两种情况:①把第k个位置的贺卡放到第一个位置,那也就是说还有n-2个贺卡没排,这n-2个贺卡与第1个第k个位置的贺卡就没有关系了,那直接把这n-2个贺卡错排,有f(n-2)种情况;②那么会产生第二种情况,就是第k个位置的贺卡如果不放到第1个位置又该怎样?(我看别人写的很多不是很清楚)这时要转换一下观念,第k个位置的贺卡不是不能放到第一个位置吗,好,我这时就把第k个位置的贺卡放到第一个位置,然后对除第一个贺卡的剩下的n-1个贺卡错排,那错排后,第k个位置的贺卡肯定不在第一个位置了,这时不就满足了条件。
这时就可以总结出公式了:只有同时完成第一步和第二部才算完成一件事,
所以:公式如上
杭电 2048
#include<stdio.h>
int f(int n)
{
int i,sum=1;
for(i=1;i<=n;++i)
sum=sum*i ;
return sum;
}
main()
{
int C,n,i,j,k;
__int64 a[21],sum;
scanf("%d",&C);
for(i=0;i<C;++i)
{
scanf("%d",&n);
sum=1;
for(k=1;k<=n;++k)
sum=sum*k;
a[1]=0;
a[2]=1;
for(j=3;j<=n;++j)
a[j]=(j-1)*(a[j-1]+a[j-2]);
printf("%.2f%%\n",(a[n]*1.0)/sum*100);
}
}
杭电 2049
#include<stdio.h> main(){ int n, m, i, k, j; __int64 str[21],sum; str[1] = 0; str[2] = 1; str[3] = 2; for(i=4; i<=20; i++){ str[i]=(i-1)*(str[i-1]+str[i-2]); } scanf("%d", &k); while(k --){ scanf("%d%d", &n, &m); sum = 1; i = 1; /*C(n, m)的排列*/ while(i<=m){ sum=sum*n/i; i ++; n --; } printf("%I64d\n", str[m]*sum); } }