Hdu 2068 RPG的错排

开始我的思路是:固定一半,另一半用组合公式cn1+cn2+cn3+cn4+.....+cni;最后用全排列减去它们即可。最后发现思路完全不对,必须用错排公式进行计算。即Cnm*a[N-m]; 从N个人中选出m个正确的,用错排公式算出(N-m)没在对应位置的个数。根据分步计数原理,可以得到结果。

CODE:

#include <stdio.h>
#include <stdlib.h>
#include < string.h>
#include <math.h>
using  namespace std;

int a[ 21];

double PaC( int n,  int m)                    // Permutation and combination.
{
     double s =  1, i;    // 小技巧,doulbe型的定义 
     for(i =  0; i < m ; i++)
        s *= (n-i)/(i+ 1);
          return s;
}


void init()                            // 错排的序列 
{
     int i;
    a[ 0] =  0; a[ 1] =  0; a[ 2] =  1;
     for( int i =  3; i <=  21; i++)
    {
        a[i] = (a[i- 1]+a[i- 2])*(i- 1);
    }
     return ;
}

int main()
{
     int N;
     int i;
     double sum;
    init();
     while(~scanf( " %d ", &N), N)
    {
         int m;
        sum =  0;
         if(N% 2 ==  0)
        {
            m = N/ 2;
        }
         else
        {
            m = N/ 2+ 1;
        }
         for(i = m; i < N; i++)
        {
            sum += PaC(N, i)*a[N-i];             // Cnm*a[N-m];即从中选出m个正确的,则有n-m个错排的。根据分步计数原理可知。 
        }
        printf( " %.lf\n ", sum+ 1);
    }
     return  0;

} 

你可能感兴趣的:(HDU)