错排公式的应用

错排公式的应用

 
定义:pala提出的问题: 十本不同的书放在书架上。现重新摆放,使每本书都不在原来放的位置。有几种摆法? 这个问题推广一下,就是错排问题: n个有序的元素应有n!种不同的排列。如若一个排列式的所有的元素都不在原来的位置上,则称这个排列为错排
 

HDOJ RPG的错排

Problem Description
今年暑假杭电ACM集训队第一次组成女生队,其中有一队叫RPG,但做为集训队成员之一的野骆驼竟然不知道RPG三个人具体是谁谁。RPG给他机会让他猜猜,第一次猜:R是公主,P是草儿,G是月野兔;第二次猜:R是草儿,P是月野兔,G是公主;第三次猜:R是草儿,P是公主,G是月野兔;......可怜的野骆驼第六次终于把RPG分清楚了。由于RPG的带动,做ACM的女生越来越多,我们的野骆驼想都知道她们,可现在有N多人,他要猜的次数可就多了,为了不为难野骆驼,女生们只要求他答对一半或以上就算过关,请问有多少组答案能使他顺利过关。

Input

输入的数据里有多个case,每个case包括一个n,代表有几个女生,(n<=25), n = 0输入结束。

 

Sample Input

1

2

0

Sample Output

1

1
 
解题思路:

求0到n/2的所有错排和

注意到对于i个人的错排的时候,还应该在错排前面乘上一个C(n,i)

代表选取i个人进行错排
 1 #include<stdio.h>

 2 #include<math.h>

 3 #define e exp(1.0)

 4 __int64 ans[30];

 5 __int64 f[30];

 6 double p(int n)

 7 {

 8      int i;

 9      double res=1.0;

10      for(i=1;i<=n;i++)

11           res=res*i;

12      return res;

13 }

14 

15 __int64 C(int n,int r)

16 {

17      __int64 res=1;

18                 __int64 i;

19      for(i=1;i<=r;i++)

20      {

21           res=res*(n-i+1);

22           res=res/i;

23      }

24      return res;

25 }

26 void init()

27 {

28      int i,j;

29      for(i=1;i<=13;i++)

30           f[i]=(__int64)(p(i)/e+0.5);   //注释1

31      ans[1]=1;

32                 f[0]=1;

33 

34      for(i=2;i<=25;i++)

35      {

36           for(j=0;j<=i/2;j++)

37                ans[i]=ans[i]+f[j]*C(i,j);

38      }

39 }

40 

41 int main()

42 {

43      int n;

44      init();

45      while(scanf("%d",&n)!=EOF)

46      {

47           if(n==0)

48                break;

49           printf("%I64d\n",ans[n]);

50      }

51      return 0;

52 }

注释1:

错排问题,对于n个元素,对其重新排列,使得恰好有m个元素在原来的位置的排列总数P(n,m)

定理:令f(n) = P(n,0),则f(n) = (n-1)*f(n-1) + (n-1)*f(n-2)

定理:P(n,m) = (n!/m!)(1 - 1/1! + 1/2! -1/3! + …+ (-1)^(n-m) * 1/((n-m)!))

当m=0时,f(n) = P(n,0) = n! * (1 - 1/1! + 1/2! - 1/3! + … + ((-1)^n)/n! )

由级数知识化简为 f(n) = (n!/e +0.5) 整数向下取整

你可能感兴趣的:(应用)