组合数学——错排有关问题及其应用

组合数学——错排问题及其应用

    n个有序的元素应有n!个不同的排列,若一个排列使得所有的元素都不在原来位置上,则称这个排列为错排。

错排公式推导

    设n个数1,2,3...,n错排数目为Dn,对于其中任意一个数i:

    (1) 数i分别与其他的n-1个数交换位置,其余n-2个数进行错排,共得到(n-1)Dn-2个错排;

    (2) 对除数i以外的n-1个数进行错排,然后i与其中每个数互换,得到(n-1)Dn-1个错排。

    因此,得到递推关系:Dn=(n-1)(Dn-1 + Dn-2),D1=0,D2=1。它的通解为Dn=n!-C(n,1)(n-1)!+C(n,2)(n-2)! - ... +(-)C(n,n)1!。

 

HDU2048

题意:给出n个元素,求错排的概率。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef __int64 int64;
const int N = 21;
int64 d[N];
int64 f[N];

int main()
{
    int i;
    int c,n;
    d[1] = 0;
    d[2] = 1;
    f[1] = 1;
    f[2] = 2;
    for(i = 3; i < N; i++)
    {
        d[i] = (i-1)*(d[i-1] + d[i-2]);
        f[i] = f[i-1]*i;
    }
    scanf("%d",&c);
    while(c--)
    {
        scanf("%d",&n);
        double p = 1.0*d[n]/f[n]*100.0;
        printf("%.2lf%%\n",p);
    }
    return 0;
}

 

 

 

HDU2068

题意:给出n个元素,求有>=一半的元素在自己的位置的组合数。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef __int64 int64;
const int N = 15;
int64 d[N];

//c(m,n),m>=n
int64 composite(int64 m, int64 n)
{
    int64 i,j;
    if(n==0)
        return 1;
    int64 result = 1;
    for(i=m,j=1; j <= n; i--,j++)
        result = result*i/j;
    return result;
}

int main()
{
    int i;
    d[1] = 0;
    d[2] = 1;
    for(i = 3; i < N; i++)
        d[i] = (i-1)*(d[i-1]+d[i-2]);
    int n;
    while(true)
    {
        scanf("%d",&n);
        if(n==0)
            break;
        int k = n/2;
        int64 result = 0;
        for(i = 2; i <= k; i++)
            result += composite(n,i)*d[i];
        printf("%I64d\n",result+1);
    }
    return 0;
}