错排问题,又称更列问题,是组合数学中的问题之一。对于它的研究最早可以追溯到十八世纪,当时他被数学家尼古拉·伯努利和欧拉研究,因此在历史上也被称为伯努利--欧拉的错装信封问题。这个问题有许多具体的版本,比如在写信时讲n封信装到n个不同的信封里,有多少种全部装错信封的情况?再比如n个人各写一张贺卡相互赠送,有多少种赠送方法?这些经典的题目都是典型的错排问题。
相信看过上面对于错排问题的简单的介绍,大家也都对它有了一些初步的了解,归结起来,就是考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就称为原排列的一个错排,n个元素的错排数记为D(n)。那么对于这样的排列D(n)有多少种呢?我们一步一步进行分析:
首先,对于D(n),有1~n这样n个元素错排,所以对于第一个元素①,它现在可能的位置有(n-1)个,倘若它在第k个元素的位置上,对于第k个元素而言,它所在的位置就有两种可能—第一种,它处在非第一个元素①位置上,所以对于接下来的排列就相当于是n-1个元素的错排,即D(n-1);第二种,它处在第一个元素①的位置上,所以在排列D(n)中有两个元素找到了位置,那么接下来的队列就相当于是n-2个元素的错排。因此,对于D(n)都有D(n)=(n-1)*(D(n-1)+D(n-2))【特殊的,D(1)=0,D(2)=1】。
错排公式的应用:HDU-2048
AC代码:
package hdu经典100题;
import java.text.DecimalFormat;
import java.util.Scanner;
/**
* 使用错排公式f[n]=(n-1)*(f[n-1]+f[n-2])
* @author Geek
* @version 1.0
* @date 2018年8月11日 下午9:55:32
* @TextDemo I hava a acDream
* @copyright
* @remark
*/
public class P2048 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int C = in.nextInt();
DecimalFormat decimalFormat = new DecimalFormat("0.00%");
double[] nums = new double[21];
nums[2] = 1;
nums[3] = 2;
for (int i = 4; i < nums.length; i++) {
nums[i] = (i-1)*(nums[i-1]+nums[i-2]);
}
while(C!=0) {
int n = in.nextInt();
double jc = 1;
for (int i = 2; i < n+1; i++) {
jc*=i;
}
System.out.println(decimalFormat.format(nums[n]/jc));
C--;
}
}
}