错排
百度一下:公式
百度一下:问题
对于有n个标号为1∼n的箱子和n个标号为1∼n的球,现在需要统计将所有的球放入箱子,每个箱子必须有且只有一个球,并且每个球的编号和装它的箱子的编号不一样的方案数。
假如n=3,那么所有情况如下:
[1](2) [2](3) [3](1)
[1](3) [2](1) [3](2)
方括号为箱子,圆括号为球,数字为编号。
我们可以用递推的方式求出方案数。我们令f[i]表示当n=i的时候的答案,那么我们新加入一个箱子和球,就有两种情况:
-
我们从原来的方案中拿出一个编号的箱子和球,有i−1种拿法,与这个新加入的交换,那么剩下的i−2个又成为了一个子问题,所以(i−1)×f[i−2]的贡献。
-
我们还可以从原来的里面拿出一个编号的箱子(不拿球),那么有i−1种拿法,然后将新的装在这个箱子里,将新的箱子和剩下的又成为一个子问题,所以有(i−1)×f[i−1]的贡献。
总的来说,我们就得到了递推式:
f[i]=(i−1)×(f[i−1]+f[i−2])
其中边界条件为f[0]=1
在百度百科的讲解中,利用容斥原理可以得到通项公式如下:
f[n]=n!×(i=0∑ni!1×(−1)i)
例题:
【IN Luogu】
本题是Imagine大佬出的,在此Orz并感谢他的讲解。
我们先算出刚好K个配对的方案数量,然后乘以剩下的错排方案数,但是这个显然不是简单的错排了,因此不能直接套用公式。
前面的刚好K个配对的就是:
- 选k排座位Cnk
- 选k对情侣Cnk
- 这k对每排可以交换坐2k
- 这k排可以任意排列k!
所以前半部分的答案就为(Cnk)2×k!×2k
那么对于错排部分,我们模仿错排递推的推导过程分类考虑,我们令g[n]为n对不匹配的方案数:
首先第一排坐两个不是情侣的人,不难发现那么可以有2n×(2n−2)种选法,剩下只有n−1个座位,对于剩下的,我们考虑另外的两个就是与开始那两个坐在一起的另一半情侣,他们有两种方案:
- 坐在一起:就是在剩下的n−1排中任选一排,且这个两个人可以交换,然后就转化为子问题g[n−2],所以贡献为2×(n−1)×g[n−2]
- 不坐在一起,我们就把他们又看作一个不能在一起的错排问题,于是贡献为g[n−1]
和错排公式结合起来,所以这部分的方案数贡献为2n(2n−2)(g[n−1]+2(n−1)g[n−2])
那么答案就是(Cnk)2×k!×2k×4n(n−1)(g[n−1]+2(n−1)g[n−2])
预处理阶乘和阶乘逆元还有g函数,然后每次O(1)的回答即可。
复杂度为O(logMod+n+T)
End