问题: 十本不同的书放在书架上。现重新摆放,使每本书都不在原来放的位置。有几种摆法?
这个问题推广一下,就是错排问题,是组合数学中的问题之一。考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就称为原排列的一个错排。 n个元素的错排数记为D(n)。 研究一个排列错排个数的问题,叫做错排问题或称为更列问题。
1.错排问题的解释
当n个编号元素放在n个编号位置,元素编号与位置编号各不对应的方法数用D(n)表示,那么D(n-1)就表示n-1个编号元素放在n-1个编号位置,各不对应的方法数,其它类推.
第一步,把第n个元素放在一个位置,比如位置k,一共有n-1种方法(如下图,把1号小球放在3号位置);
第二步,放编号为k的元素,这时有两种情况:
(1)把它放到位置n,那么,对于剩下的n-1个元素,由于第k个元素放到了位置n,剩下n-2个元素就有D(n-2)种方法;
(把被占的3号位置所对应的3号小球放置在1号位置,相当于2个位置已被预订,去除这两个位置后,原问题缩小为n-2规模的 问题,即有D(n-2)种方法)
(2)第k个元素不把它放到位置n,这时,对于这n-1个元素,有D(n-1)种方法;
(若不把3号小球放置在1号位置,对于这未放置的n-1个小球和n-1个位置,原问题缩小为n-1规模的问题,即有D(n-1)种方法)
综上得到
D(n) = (n-1) [D(n-2) + D(n-1)]
Java代码实现:
//错排的公式 private static void wrongsort() { a[0] = 0; a[1] = 0; a[2] = 1; for(int i = 3; i < n; i++){ a[i] = (i - 1) * (a[i-1] + a[i-2]); } }
2.问题描述
今年暑假杭电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输入结束。
3.解题思路
题目要求排列对一半或以上,问题可转化为:假设总女生数n中有m个位置排错了(m<n/2),即为m个元素的错排与这m个元素的组合之积(给排错的女生排在不同错误的位置的机会)。
1)计算出错排的答案数;2)计算出对应排错女生数量的不同组合总数;3)重复步骤1~2,依次算出少于一半人数下的组合错排方案数。
Java实现代码:
import java.util.Scanner; public class Main { static int[] a = new int[14]; public static void main(String[] args) { wrongsort(); Scanner in = new Scanner(System.in); while(in.hasNextInt()){ int n = in.nextInt(); if(n == 0){ break; } long sum = 1; for(int i = 2; i <= n/2; i++){ sum += C(n,i) * a[i]; } System.out.println(sum); } } //组合数 private static double C(int n, int m) { double s = 1; for(int i = 0; i < m; i++){ s = s * (n - i) / (i + 1); } return s; } //错排 private static void wrongsort() { a[0] = 0; a[1] = 0; a[2] = 1; for(int i = 3; i < 14; i++){ a[i] = (i - 1) * (a[i-1] + a[i-2]); } } }(更多解题代码及解释在 git)
参考资料:
1. 错排公式_百度百科