• ACM -- 算法小结(二)错排公式的应用


    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
    ",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) 整数向下取整

  • 相关阅读:
    那些年搞不懂的多线程、同步异步及阻塞和非阻塞(二)---概念区分
    那些年搞不懂的多线程、同步异步及阻塞和非阻塞(一)---多线程简介
    websocket简单实例
    map对象拷贝问题
    【简单算法】44.位1的个数
    【简单算法】43.罗马数字转整数
    【简单算法】42. 3的幂
    【简单算法】41.计数质数
    【简单算法】40.Fizz Buzz
    【简单算法】39.最小栈
  • 原文地址:https://www.cnblogs.com/lmei/p/3216460.html
Copyright © 2020-2023  润新知