错排问题-hdu2048

错排介绍

n个有序的元素有n!种排列方式,如果一个排列使得所有元素都不在原来的位置上的排列就叫错排。

错排推导

(1)错排有两种方法进行计算,一种是基于容斥定理最后得出来的一个阶乘的计算式,计算机对于阶乘非常的不友好,因此第一种很少使用。

(2)由于阶乘的原因,我们不得不再寻找一种计算错排Dn的方法。
首先我们以1,2,3,4的错排为例子,
(1,2)的错排唯一,是(2,1)
(1,2,3) 的错排是 (3,1,2)(2,3,1)。这两种都可以看作是 (1,2) 的错排的每一位元素和3进行交换位置得到。如图
在这里插入图片描述

(1,2,3,4) 的错排可以表示为

(4,3,2,1) 前三个总结为4与1,2,3,分别换位,另外两个元素错排
(3,4,1,2)
(2,1,4,3)

(4,1,2,3) 中间三个是4和3,1,2(1,2,3的错排一种)每一位进行交换
(3,4,2,1)
(3,1,4,2)

(4,3,1,2) 最后三个是4和2,3,1(1,2,3的错排的另外一种)每一位进行交换得到
(2,4,1,3)
(2,3,4,1)

由上面可以得到错排的第二种方法:
从1,2,3…n中任取一个数字i,分别和其他的n-1个数中的随便一个互换,然后剩下的n-2个数字进行错排,共得到(n-1)Dn-2种错排。还有就是 i 以外的n-1个数字进行错排,i和n-1的错排中的每一个数字进行交换,共得到(n-1)Dn-1个错排。最后结果为二者加起来。

Dn = (n-1)(Dn-1 + Dn-2) (D1 = 0, D2 = 1)
通过这个递归公式就能很轻松的求出来错排结果了。

例题地址

hdu2048

例题讲解

非常直观的错排题,只要注意别用int就行了,还需要注意的是再printf中输出%需要打两个%%。

AC代码

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
	int ans;
	
	scanf("%d", &ans);
	
	while (ans--)
	{
		int n;
		
		scanf("%d", &n);
		
		double a[30];
		double sum = 1;
		
		memset(a, 0, sizeof(a));
		a[1] = 0;
		a[2] = 1;
		
		for (int i=1; i<=n; i++)
			sum*=i;
			
		for (int i=3; i<=n; i++)
			a[i] = (i-1) * (a[i-1] + a[i-2]);
			
		printf("%0.2lf%%\n", a[n]*100/sum);   //两个百分号才能输出一个百分号 
	}
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值