错排递推公式的证明

书架上面有n本书,我们打乱次序重新排,要求每本书重新排好之后位置要与之前不同,那么有多少种排放的方法。

首先,我们从规模较小的数据出发。

如果是一本书,那么不会出现错拍,则f[1] = 0;

如果是两本书,那么两两交换会出现一次错排,则f[2] = 1;

如果是三本书,那么错排次数是2,令原序是(1, 2, 3),则错排可以是(3, 1, 2),(2, 3, 1),即f[3] = 2;

………………………………

那么我们来推倒一下这个公式;

要求n个数的错排方法

那么首先,第一个数1有n-1种放法①(除去自身之外的位置都可以放)

然后我们来看剩下的n-1个数

那么这n-1个数有两种不同的选择

1.其中一个数选择之前数离开的位置k放置自身,那么这组数剩下的需要错排的数为n-2②,我们需要继续求n-2的错排数

2.不选择之前一个数离开的位置进行放置而重新选择另外一个位置进行放置,则位置k空了出来,且位置k属于n-1个数允许放置的范围,于是我们需要求n-1③个错排数

那么②+③错排数的情况总和则是当选择一个数之后数字错排的所有可能,可以随机选取n个数,则存在n-1种选择的方案

所以总的错排次数为①×(f②+f③),即f(n) = (n-1)*(f(n-1) + f(n-2))

PS:hdu2049是一道错排+组合数的题目,贴上AC代码用作参考

因为有n对新人,其中m个新郎认错,总可能次数为C(n, m)

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
long long int cal(int n)	
{
	long long int ans = 1;
	for (int i = 1; i <= n; i++)
		ans *= i;
	return ans;
}
int main()
{
	int c, n, m;
	scanf("%d", &c);
	while(c--)
	{
		long long int a[22] = {0};
		a[1] = 0;
		a[2] = 1;
		scanf("%d %d", &n, &m);
		for (int i = 3; i <= m; i++)
			a[i] = (i-1) * (a[i-1] + a[i-2]);
		printf("%I64d\n", cal(n) / (cal(m) * cal(n - m)) * a[m]);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值