错排详解及案例

错排详解及案例

文章目录

  • 错排详解及案例
    • 一、错排详解
    • 二、案例
      • 1.年会抽奖
      • 2.三国佚事——巴蜀之危

一、错排详解

问题:现有10本书按照顺序摆放,现要求重新排列,使得新的书的顺序中每一本书都不在原来的位置,求有多少种排列方式?

  • 这个问题推广一下,就是错排问题,是组合数学中的问题之一。
  • 考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就称为原排列的一个错排n个元素的错排数记为D(n)。 研究一个排列错排个数的问题,叫做错排问题或称为更列问题
  • OK,现在详细分析这个问题,我们要的最终结果就是书的编号与所在位置的编号都不相同,在这里,我们把n本书的错排操作数记为D(n),那n-1本就是D(n-1),n-2本就是D(n-2)啦,下面,我们把放置问题分为两步(初始位置号与书的编号相同):
  • 第一步:
  • 我们取一本书,书的编号为m,现在这本书就在我们手中,注意,按照题目要求,最开始的时候这本书的位置号也是m号,按照题目要求,我们现在放书时不能放回这个位置m了,而是要选择其他位置,那么有多少种选择呢
  • 想一下,总共有n本书,n个位置,现在我手里这本书不能把它放到位置m,那么剩下的n-1个位置我当然就是随便扔啦,也就是n-1种扔法
  • 好,现在,我选择了位置k,我决定把手里这本书放到位置k这里,记住这个是位置编号k,那么,我肯定要把原来这里的编号为k的书拿出来,再把这本编号为n的书放进去喽。所以,现在我们手里的书的编号是k,我们需要对编号为k的书进行讨论:
  • 第二步:
  • 我们把手里这本编号为k的书本放到书架,注意,放的过程中我们又面临两种情况:
  • 可以想到,此时此刻现在书架上编号m的位置是空着的,所以我们可以选择放在这个位置上,书的编号为k,位置编号为m,没错,满足题意,这是第一种情况
  • 还有一种就是我不选择这个空着的位置m,我再重新选择一个新的位置,我们称之为第二种情况。下面详细分析:
  • 第一种情况:
  • 我把这本编号为k的书放到这个编号为m的地址,那现在我们面前是什么状况呢,就是位置k和位置m的书交换位置,也就是位置号不等于书号,即满足错排
  • 总共n个位置,我们只动了m和k这两个位置,那么剩下的n-2个位置还是纹丝不动,保持一一对应的关系
  • 那么对于剩下的这n-2本书的错排操作,我们又回到了问题的起点,求n-2本的错排操作数D(n-2),结合第一步,我们可以得到第一种情况总共有(n-1)*D(n-2)种方法
  • 第二种情况:
  • 我们不选择这个空着的位置m啦,我们手持这本编号为k的书,我们从除了位置m以及位置k的剩下的n-2个位置中选择一个位置
  • OK,我们现在开始想,我手里这本书不能放在这个位置m,嗯嗯,除了第一步我们放置的那本书m不用管了,我们还要把手里这本和剩下的n-2本,也就是n-1本,同时又要求手里这本k还不能放到位置m,这是不是就相当于把手里这本加上剩下的n-2本也就是n-1本书进行错排呢
  • 哇哇哇,想一想,错排的定义,要求每本书都不能呆在某一个特定位置,是不是刚好符合呢qwq,所以,现在的问题就到了求手里这本和剩下的n-2本总共是n-1本书的错排操作数,我们记为D(n-1),结合第一步,我们得出这第二种情况共有(n-1)*D(n-1)种方法
  • 好的,现在我们总结两种情况,结果进行相加,就可以得到递推公式啦!递推公式为:D(n)=(n-1)*[D(n-1)+D(n-2)]

二、案例

1.年会抽奖

  • 问题描述

今年公司年会的奖品特别给力,但获奖的规矩却很奇葩:

  1. 首先,所有人员都将一张写有自己名字的字条放入抽奖箱中;
  2. 待所有字条加入完毕,每人从箱中取一个字条;
  3. 如果抽到的字条上写的就是自己的名字,那么“恭喜你,中奖了!”
    现在告诉你参加晚会的人数,请你计算有多少概率会出现无人获奖

输入描述

输入包含多组数据,每组数据包含一个正整数n(2≤n≤20)。 

输出描述

对应每一组数据,以“xx.xx%”的格式输出发生无人获奖的概率。

示例1

输入
2

输出
50.00%
  • 代码
#include
using namespace std;
 
double luck(double n)
{
	if(n == 1 || n == 2)
	{
		return n - 1;
	}
	
	return ((n - 1)*(luck(n - 1) + luck(n - 2)));
}
	
int main()
{
	double n;
	while (cin >> n)
	{
		//错排的方案数
		double lu = luck(n);

		//总的方案数
		double all = 1;
		for (double i = 1;i <= n;++i)
		{
			all *= i;
		}
		
		//概率
		lu = lu / all*100;
		
		printf("%.2f%%\n", lu);
	}
	return 0;
}

2.三国佚事——巴蜀之危

  • 问题描述

话说天下大势,分久必合,合久必分。。。却道那魏蜀吴三国鼎力之时,多少英雄豪杰以热血谱写那千古之绝唱。古人诚不我欺,确是应了那句“一将功成万骨枯”。
是夜,明月高悬。诸葛丞相轻摇羽扇,一脸愁苦。原来是日前蜀国战事吃紧,丞相彻夜未眠,奋笔急书,于每个烽火台写下安排书信。可想,这战事多变,丞相运筹 帷幄,给诸多烽火台定下不同计策,却也实属不易。

谁成想这送信小厮竟投靠曹操,给诸葛丞相暗中使坏。这小厮将每封书信都投错了烽火台,居然没有一封是对的。不多时小厮便被抓住,前后之事却也明朗。这可急坏了诸葛丞相,这书信传错,势必会让蜀军自乱阵脚,不攻自破啊! 诸葛丞相现在想知道被这小厮一乱,这书信传错共有多少种情况

Input

 题目有多组数据,处理到文件结尾,丞相共写了n(1 <= n <= 20)封书信,输入一个正数n。

Output

   输出书信传错的情况数。
Sample Input

1
3
6
Sample Output

0
2
265
#include 
typedef long long LL;

LL f[50] ; 
int main()
{
	f[0] = 0 ;
	f[1] = 0 ;
	f[2] = 1 ;
	
	int n ;
	for(int i = 3 ;i<= 20 ; i++)
	{
		f[i] = (i - 1) * (f[i - 1] + f[i - 2]) ;
	}
	
	while(~scanf("%d",&n))
	{
		printf("%lld\n",f[n]);
	}
	
	return 0 ;
}

你可能感兴趣的:(算法)