当前位置:编程学习 > C/C++ >>

错排详解

错排问题

一个寝室有四个人,过节时,每个人都会送出一封贺卡,假如一个盒子里有四封贺卡,寝室的每个成员都要拿出一封,但是肯定不能拿自己写的贺卡,如果每个人拿到的是别人送的贺卡,问这种情况有多少种?

这就是典型的错排问题。

先给出公式: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

[cpp] 
#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

[cpp]
#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); 
    }    

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,