博客园食用更佳
关注洛谷谢谢喵~
基本定义在此不再过多阐述,介绍一下基本符号:
(mn)=Cnm,含义为 n 选 m 的组合方案数。
Anm,含义为 n 选 m 的排列方案数。
求组合数方式
一般采用预处理阶乘与逆元做到线性求组合数。
如果求 (mn) 时 n 极大而 m 较小,此时无法预处理 n 的阶乘和逆元,可以采用下降幂运算,即预处理 m 的阶乘和逆元,将原式写为:
(mn)=i=n−m+1∏n×m!1
这样就可以用较快的时间来求出组合数。
Fn=i=0∑n(in)×(n−i)!×(−1)i=n!×i=0∑ni!1×(−1)i
乘号后面进行预处理即可。
- 使用递推:设填后的序列第 i 为 pi,将 i 向 pi 连边。考察 1 所在的环,设其长度为 i。去掉 1 所在的环,剩下的数的方案数为 Fn−i。所以枚举 i,同时计算长度为 i 环上的数方案数,有:
Fn=i=2∑nFn−i×(n−i)!(n−1)!=(n−1)!×i=0∑n−2i!Fi
在计算 Fn 的同时,维护乘号后面的式子。
- 依然是递推:对上文的递推进行简化,仍然考察 1 所在的环,将 1 去掉同时将环上和 1 相邻的两个点连上,等价于对后面 n−1 个数做错排。注意当 1 所在环只有 1 和另外一个点的时候,由于点不能指向自己,此时相当于对剩下 n−2 个数做错排。
还有一种理解方式,考虑现在已经有一个合法的错排图,要向里面加入一个点,则可以在任意一条边加入该点,但这样只考虑到了新加入的点所在环长度大于 2 的情况,所以还需考虑在其中取出一个点,与新加的点互相连边,剩下的点形成一张错排图。
综上有:Fn=(n−1)(Fn−1+Fn−2)。
观察数据范围,猜测最终时间复杂度为 O(k2)。
发现方格宽度为 2,只能容下大小为 1,2 的方块竖着放,不妨将 1 看作横着放,所以只需要考虑有多少个 2 竖着放即可,设个数为 i,对 i 进行枚举,时间消耗为 O(k),其中 i∈[0,k]。
现在问题化为两个子问题,一个为选竖着的 2 的方案数,一个为放完竖着的 2 后整个网格横着放的方案数。不妨先考虑第二个子问题。
先思考没有竖着的 2 的方案数。将其展开为 1×2n 的平面,考虑插板,由于已经有两个基本块,所以只需要再插 k−2 个板,而在 n 与 n+1 之间无法插板,所以可供插板空隙为 2n−2,故方案数为 (k−22n−2)。
现在考虑有竖着的 2 情况,由于枚举了竖着的 2 的数量,设其为 i。因为该数量固定,所以影响空隙个数的只有形成的连通块个数,设其为 j,则空隙个数即为 2(n−i)−2j。同理,可供插的板也只与连通块个数有关,为 k−i−2j。故最终方案数为 (k−i−2j2(n−i)−2j)。故需要枚举形成连通块数量,时间消耗为 O(k),其中,j∈[1,i+1]。
接着考虑第一个子问题。由于需要分成 j 个连通块,所以用来分隔网格的竖着的 2 的连通块个数即为 j−1。但是如果竖着的 2 放在了开头或者末尾是不会影响网格连通块个数的,所以 2 连通块个数还可以为 j,j+1。对这个问题做插板,发现可以插 j+1 个板,而可供插板的空隙为 i 个的开头结尾和中间共计 i+1 个位置。所以该问题方案数为 (ji+1)。
最后考虑放着这些连通块到网格的方案数,相当于将剩下的 2×(n−i) 个格子分为 j 块,仍然用插板法,得知方案数为 (j−1n−i−1)。
发现有一种情况没有考虑,即 n=k 时选 k 个竖着的 2 的方案,这种情况无法刻画,因为没有形成连通块,最后特判加上即可。
最终答案为:
i=0∑kj=1∑i+1(k−i−2j2n−2i−2j)×(ji+1)×(j−1n−i−1)+[n=k]=i=0∑kj=0∑i(k−i−2j−22n−2i−2j−2)×(j+1i+1)×(jn−i−1)+[n=k]
可能空间开不下,但是发现可以预处理后两个组合数的阶乘和逆元,对前一个组合数只预处理阶乘,求的时候现求逆元即可(或者都开成 int,强转 longlong)。
广义组合数
-
当 n≥m≥0 时,(mn)=(n−m)!m!n!
-
当 m≥0∧m≥n 时,(mn)=m!∏i=n−m+1ni
-
由二式得,当 m≥n≥0 时,有:
(m−n)=m!∏i=−n−m+1−ni=(n−1)!m!(n+m−1)!×(−1)m=(−1)m×(mn+m−1)
首先可以做一个简单的 dp,dpi,j 表示考虑 [1,i] 中的数,选了 j 个数在序列中的权值积,最后 dpk,n×n! 即为答案。
观察 dp 转移:dpi,j=dpi−1,j+dpi−1,j−1×i,发现转移系数和 i 有关,故矩阵快速幂中的转移矩阵不固定,没有前途。
本题生成函数对于笔者来说太过困难,所以在此只讨论使用拉插解题。
发现 dp 转移非常简洁,所以猜测对于固定的 j,dpi,j 在一个多项式上。设 g(fx) 表示 fx 的多项式次数,则显然有,g(fx−fx−1)=g(fx)−1。观察 dp 转移式子,有:
dpi,j=dpi−1,j+dpi−1,j−1×idpi,j−dpi−1,j=dpi−1,j−1g(fj)−1=g(fj−1)+1
又因为 g(f0)=0 次,所以 g(fj)=2j。因此只需要做 2n+1 次 dp,然后拉插即可。
发现值域为 [0,m],则一行只有一个位置会 +2,可以做出来简单 dp,优化过后变为 dpi,j=dpi,j−1+dpi−1,j+1。
代数推导一点不会,组合意义天崩地裂。
发现式子很简洁,想用上一题的方法看看多项式,发现次数为 n,那肯定没救的。所以考虑组合意义,将其放在网格图上,考虑将 dp 值变为到达 (i,j) 的路径条数,dp 转移看为一条边。发现转移中有斜着的边,不好处理,所以将其平移。发现行末仍然有一条斜边,将其扩展为先向右再向下,于是得到一张网格图。由于将每一行行末扩展了,所以每一行长度为 m+1,则问题变为在网格图上,从原点出发,到达 (n+m+1,n) 的方案数,网格形状如下:

将网格形状转化为限制,变为不接触两条直线的方案数。称直线 A 为上方直线,直线 B 为下方直线,点 P 为 (n+m+1,n)。考虑反射容斥,即将总方案数即从原点到 P 的路径数,减去碰到任意一条直线且可能越过直线的方案数,将碰到的直线依次写为一个序列,相邻相同的直线进行缩点,最后会得到 ⋯ABAB 或 ⋯BABA,将不合法方案分为末尾为 A 的方案和末尾为 B 的方案。发现将 P 沿直线 A 对称得到 P′ 后,每一条从原点到达 P′ 的路径都可以通过从第一次接触 A 开始对称,最终到达 P;同理,每一条从原点到达 P 且接触了 A 的路径都可以从第一次接触 A 开始对称,最后到达 P′,所以形成了双射。考虑这类方案对应接触序列是怎样的。考虑到达 P 且接触 A 的路径中从最后一次接触 A 到 P 的路径,由于为最后一次接触 A,所以不会再碰到 A,只有可能碰到 B。所以这类路径个数对应序列结尾为 A 或 AB 的序列个数;同理,若将 P 沿 B 反转,可以得到序列结尾为 B 或 BA 的序列个数。发现总共多减去结尾为 AB 和 BA 的序列个数。考虑将 P′ 再次沿 B 对折,仍然考虑从原点到 P′′ 的路径中最后一次接触 B 来看,后面一定会接触 A,然后可能在去往 P 的路径上再次接触 B,所以路径末尾为 BA 或 BAB。
所以有一个简单的容斥,发现 P,P′,P′′⋯ 形成的直线斜率为 −1,每两次对称一定会向 x,y 轴移动,所以至多移动线性次,所以时间复杂度为线性。
第一类斯特林数
s(n,k) 表示 n 个数,分为 k 个环(即 1,2,3,4 与 4,1,2,3 算一种方案)的方案数,记作 [mn]。
有递推式:s(n,k)=s(n−1,k−1)+s(n−1,k)×(n−1)。代表新加入的点是新增一个环还是插入到原有的环中共 (n−1) 个位置中。
有性质:
-
s(n,1)=(n−1)!,易证。
-
s(n,2)=(n−1)!×∑i=1n−1i1,证明考虑数学归纳法。
-
∑k=1ns(n,k)=n!。考虑任意一个排列都可以通过 i→ai 连边来映射成唯一一个由若干个环组成的图;同理,环也可以映射成唯一一个排列。二者形成双射。
下降幂
有 xi=(x−i)!x!。文章开头即为下降幂优化求组合数式子。
其与组合数相乘有着优雅的形式,如下:
(kn)×km=(n−k)!(k−m)!n!=(n−k)!(k−m)!(n−m)!×(n−m)!n!=(n−kn−m)×nm
发现原本式子中两个乘数都含有 k,转化完后只有一个式子含有 k。
第二类斯特林数
S(n,k) 表示 n 个数,分为 k 组,每组无序,组与组之间没有区别的方案数,记作 {mn}。
有递推式:S(n,k)=S(n−1,k−1)+S(n−1,k)×k。代表新加入的点是新增一组还是加入原有的 k 组中。
第二类斯特林数可用于转化幂:xn=∑i=1n{in}xi,证明考虑数学归纳法:
xn=x×xn−1=x×i=1∑n−1{in−1}xi=i=1∑n−1{in−1}xi(x−i)+i=1∑n−1{in−1}xii=i=1∑n−1{in−1}xi+1+i=1∑n{in−1}xii=i=1∑n{i−1n−1}xi+i=1∑n{in−1}xii=i=1∑n{in}xi
发现原式为 k 的次幂乘上关于 k 的组合数,因为 k 很大,不能枚举,这个形式有不是那么好看,所以使用下降幂来将其优化一下。将原多项式变为下降幂多项式,设 f(x)=∑i=0mbiki,然后开始转化:
=====k=0∑nf(k)xk(kn)k=0∑ni=0∑mbikixk(kn)k=0∑ni=0∑mbi(k−in−i)nixki=0∑mbinik=0∑n−i(kn−i)xk+ii=0∑mbinixik=0∑n−1(kn−i)xki=0∑mbinixi(x+1)n−i
则问题转化为求 bi。
因为有 xn=∑i=0n{in}xi,所以将 f(x) 进行转化:
f(x)=i=0∑maixi=i=0∑maij=0∑i{ji}xj=i=0∑mxij=i∑maj{ij}
可以递推预处理出所有第二类斯特林数,然后 O(m2) 求出所有 bi,最后 O(m2) 求出答案。
总时间复杂度 O(m2)。
有帮助,赞一个