一些典型的计数

这里将会记录一些典型的计数。

图计数

无向图计数

显然,n 个点的无向图个数应该为 2(n2)

n 个点 m 条边无向图计数

不妨设 g(n,m) 表示 n 个点 m 条边的无向图个数,显然有

g(n,m)=((n2)m)

f(n,m) 表示 n 个点 m 条边的无向连通图个数。对于无向图,枚举 1 号点相连的连通块大小以及边数,可以得到下面等式:

g(n,m)=anbm(n1a1)g(na,mb)×f(a,b)

f(n,m) 的项分离出来,我们可以得到:

g(n,m)=f(n,m)+a<nbm(n1a1)g(na,mb)×f(a,b)+anb<m(n1a1)g(na,mb)×f(a,b)a<nb<m(n1a1)g(na,mb)×f(a,b)

这个公式看起来有点繁琐,不妨设 H(n,m,x,y) 表示 anbm(n1a1)g(na,mb)×f(a,b),移项后不难得到:

f(n,m)=g(n,m)h(n,m,n1,m)h(n,m,n,m1)+h(n,m,n1,m1)

复杂度达到 O((nm)2)。使用斯特林反演可以做到 O(n2m)

n 点无向连通图计数

和上面的思路基本相同。最暴力的思路是枚举 1 号节点所在连通块的大小。

不妨设 g(n) 表示 n 个点的 无向图 个数,f(i) 表示 n 个点的 无向连通图 个数,那么有:

g(n)=in(n1i1)f(i)g(ni)

f(n) 分离并移项,可以得到:

f(n)=g(n)i<n(n1i1)f(i)g(ni)

这个做法是 O(n2) 的。

接下来你发现,若设出 f,gEGF 分别为 F,G,上述式子可以直接分治 NTT。这样可以做到 O(n polylog(n)) 的复杂度。

具体题目可以见 ACW #307

树的拓扑序计数

这里的树指的是一棵根向树。

  • 使用树形 dp 求解
    不妨设 fu 表示以 u 为根的树的拓扑序计数。不妨设其有两个儿子 v1,v2。这里的转移不可以将 fv1,fv2 简单相乘,还应该考虑两个子树之间的错排顺序。考虑从 szv1+szv2 中选出 szv1 个放在前面,其余的放在后面。那么有方程

fu=fv1×fv2×(szv1+szv2szv1)

推广到一般树,就有

fu=(szu1)!vson(u)fvszv!

时间复杂度 O(n)

  • 使用生成函数求解

不妨设 [xi]Fu(x) 表示 u 子树选择了 i 个节点的拓扑序方案数。F 为方案数的 EGF。那么有

Fu(x)=xFv(x)

其中乘上 x 表示选择自己的方案数。

使用 NTT 即可做到 O(nlogn)。所求即为 [xn]F1(x)

二叉树计数

著名的卡特兰数。不妨设 f(i) 表示 i 个点的二叉树个数。那么有递推式:

f(n)=f(i)f(ni1)

这是卡特兰数的递推式,答案就是

C(n)=(2nn)n+1

特殊二叉树计数

CF438E The Child and Binary Tree

给定集合 S,每个节点权值需要 S。二叉树的权值定义为其所有节点的权值和。求权值为 m 的二叉树总数。

发现是上一道题的强化版。普通二叉树计数是这道题 S={1},m=n 的弱化版。

不妨设 [xn]f(x) 表示总和为 n 的满足条件的二叉树个数,g(x)=[iS]xi,则有

f(x)=g(x)×f(x)×f(x)+1

其意义为:左子树方案为 f,右子树方案为 f,本身方案为 g,加上空树。

解二次方程得到

f(x)=1+14g(x)2g(x)

上多项式就可以了。如果嫌麻烦可以分子有理化一下。

竞赛图三元环计数

CF1264E Beautiful League

考虑容斥。如果是无向完全图,则三元环个数显然是 (n3)。减去不合法的方案即可。

不合法的方案就是从 u 出发的两条同向边。所以总方案即为

(n3)u(du2)

球盒问题

Update on 2024/2/29:对某些进行了生成函数的理解。

若干个小球放进若干个盒子的方案计数。按照盒子 / 小球的限制分为

  • 小球有标号 / 无标号

  • 盒子有标号 / 无标号

  • 每个盒子至多放一个 / 至少放一个 / 无限制

共有 2×2×3=12 种选法。故称 12 球盒(12 重计数法)。

只能掌握比较简单的。比较困难的无法掌握。

小球有标号,盒子有标号,无限制

每个小球可以在 m 个盒子中选择。所以答案为 m×m×m=mn

生成函数理解:由于小球和盒子都不相同,因此都考虑其 EGF。盒子的 EGFex,则答案为

[xnn!]emx=mn

小球有标号,盒子有标号,每个盒子至少放一个

考虑容斥。强制有 i 个盒子里没有球,那么 n 个球要放进剩下 mi 个盒子里,方案数为 (mi)n。由于盒子有标号,所以还要乘以一个 (mi)。因此总方案数就是:

i=0m(1)i(mi)(mi)n

生成函数理解:每个盒子的 EGFex1,表示抠掉选 0 个的方案。答案即为

[xnn!](ex1)m

使用二项式定理展开,可以得到:

[xnn!](ex1)m=[xnn!]i=0m(mi)eix(1)mi=[xnn!]i=0m(mi)in(1)mi

小球有标号,盒子有标号,每个盒子至多放一个

如果 n>m 肯定无解。假设 nm,那么有 mn 个盒子是空的。选出这 mn 个盒子,方案数为 (mmn)。由于小球有标号,所以还要乘以小球的排列数。答案即为:

n!(mmn)=n!(mn)=mn_

生成函数理解:每个盒子生成函数为 1+x,表示选 0/1 个。答案即为:

[xnn!](1+x)m=mn_

小球无标号,盒子有标号,每个盒子至少放一个

插板法。将 n 个小球排成一排,在 n1 个空里面插入 m1 个板子,分成 m 份。答案即为

(n1m1)

生成函数理解:盒子的生成函数为 x1x。这是由于每个盒子放 1+ 都有一种方案,其生成函数为 11x。但是去掉不放小球的方案,即为 11x1=x1x。所求即为

[xn](x1x)m=[xn]xm(1x)m=(n1m1)

小球无标号,盒子有标号,无限制

插板法变形。将 n 个小球排成一排,在后面再加入 m 个小球,现在小球总数为 n+m。将 m1 个板子插到 n+m1 个空里,将小球分成 m 份。分完之后,再从每一组里抽走一个小球,即可将每个盒子至少放一个转化为每个盒子里放 0 个。总方案数即为:

(n+m1m1)

生成函数理解:每个盒子的 OGF11x

[xn](11x)m=1(m1)!×(n+m1)m1_=(m+n1m1)

注:这里很有可能是不对的。

小球无标号,盒子有标号,每个盒子至多放一个

思路和 小球有标号,盒子有标号,每个盒子至多放一个 类似。如果 n>m 无解。然后从 m 个盒子里选出 n 个非空盒子即可。这里由于小球无标号,所以不需要乘以 n!。答案即为

(mn)

小球有标号,盒子无标号,无限制

就是 第二类斯特林数

{nm} 表示 n 个有标号小球放进 m 个盒子(盒子非空)的方案数,则有递推

{nm}={n1m1}+m×{n1m}

对于该式的理解:第 n 个小球单独放一个盒子,加上和其他 n1 个小球放一个盒子。

可以做到 O(n2) 的递推。多项式做法已经不想懂了。

对于该题,答案即为

im{ni}

小球有标号,盒子无标号,每个盒子至多放一个

能放下就是 1,否则就是 0

小球有标号,盒子无标号,每个盒子至少放一个

和第二类斯特林数定义相同。方案即为

{nm}

小球无标号,盒子无标号,每个格子至多放一个

能放下就是 1,否则就是 0

小球无标号,盒子无标号,无限制

定义“划分数” P(n,m),表示将 n 划分成 m 个非负整数的方案数。则有

P(n,m)=P(nm,m)+P(n,m1)

对于这个式子的理解:显然,对于划分出来的所有数都为整数的情况,将他们全部减一,可以建立到 P(nm,m) 的双射。对于有 0 的情况,可以看做在后面加了一个零进去,方案数为 P(n,m1),加入多个零可以通过这个递归定义。

显然可以多项式,但是我已经不想学了。所以这是一个 O(n2) 的算法。

小球无标号,盒子无标号,每个盒子至少放一个

将每个盒子里先钦定一个球,然后就是上一问的做法。方案数即为

P(nm,m)

其他计数

错排数

对于一个排列 p,若满足 in,pii,则称 p 为长度为 n 的一个错排。

Dn 表示长度为 n 的错排的个数。有递推式:

Dn=(n1)(Dn1+Dn2)

对这个递推式的解释:考虑第 n 个数放在那里。显然不能放在位置 n。假设放在了位置 i,则位置 i 的数有两种选择:放在 n 和不放在 n。对于放在 n,剩下的方案数就是 Dn2,对于不放在 n,剩下的方案就是 Dn1。枚举 in1 中选择。故有上式。

部分错排数

对于长度为 n 的,有 m 个数错排的排列进行计数。

首先选出 m 个错排的数,再乘上错排数即可。方案数即为

(nm)Dm

卡特兰数

上文中二叉树的计数使用了卡特兰数。其符号一般记做 C(n)

卡特兰数有递推式:

C(n)=i<nC(i)C(ni1)

通过生成函数等方法,我们可以求出他的另外两个表达式。这两种表达式允许 O(1) 地计算其值。

  • C(n)=(2nn)n+1

  • C(n)=(2nn)(2nn1)

卡特兰数最典型的模型是这样的:在 n×n 的网格图中,从原点出发到 (n,n) 点,不经过直线 y=x 的路径数目。其他问题大多可以转化为这个模型。

卡特兰数典型问题:

  • 某些网格路径计数

  • 合法括号计数

  • 二叉树计数

  • 多边形三角形划分

第一类斯特林数

n 个不同元素划分为 m 个圆排列的方案数,记做 [nm]

考虑递推求第一类斯特林数。有递推式:

[nm]=[n1m1]+(n1)[n1m]

对该公式的理解:第 n 个元素有两种放法:自己单独成为一个圆排列或者与前面的元素共同构成圆排列,这分别对应上式中的两项。

read(n, m); S[0][0] = 1;
rep(i, 1, n) rep(j, 1, m)
    S[i][j] = (S[i - 1][j - 1] + (i - 1) * S[i - 1][j] % mod) % mod;
printf("%lld\n", S[n][m]); return 0;

第二类斯特林数

12 重计数法中有提到。其定义为:将 n 个不同元素划分成 m 个非空集合的方案数。递推式为:

{nm}={n1m1}+m×{n1m}

其理解可以查阅上文球盒问题小球有标号,盒子无标号部分。

read(n, k); S[0][0] = 1;
rep(i, 1, n) rep(j, 1, k)
    S[i][j] = (S[i - 1][j - 1] + j * S[i - 1][j] % mod) % mod;
printf("%lld\n", S[n][k]); return 0;

贝尔数

B(n) 表示将 n 个不同元素划分成若干个非空子集的方案数。

很显然的,我们已经有了一个 O(n2) 的递推式。根据第二类斯特林数,我们只需要将斯特林数行求和即可。故有

B(n)=kn{nk}

下面介绍另一个递推公式:

B(n+1)=kn(nk)B(k)

对于这个公式的理解:对于第 n+1 个数,如果其单独被分到一类,剩下 n 个,则方案数为 (nn)B(n)。如果和某一个分到一个集合,则剩下 n1 个,方案数为 (nn1)B(n1)。以此类推。

B[0] = 1;
rep(i, 1, n) rep(k, 0, i - 1) (B[i] += B[k] * C(i - 1, k) % mod) %= mod;

不同计数常见值

省选临近,最重要的事情莫过于学会各种乱搞技巧。

对于计数题,最常见的方法是打表 + 瞎几把凑系数。所以能够通过表观察出系数是很重要的能力。

下面给出一些常见系数的表:

  • 第一类斯特林数

01234501101201130231406116150245035101

  • 第二类斯特林数

012345011012011301314017615011525101

  • 卡特兰数

012345611251442132

  • 错排数

01234560012944265

  • 划分数

012345011111110111112012222301233340134555013567

  • 贝尔数

012345611251552203

posted @   Link-Cut-Y  阅读(116)  评论(6编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
点击右上角即可分享
微信分享提示