程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 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); 
    }    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved