OI wiki 新增加的一页,在 GF 计数领域非常有用,所以总结一下。
一些符号约定
符号化方法是把组合对象(比如树,字符串,图等我们关心它组合意义的东西)转化为 GF 形式表达的一种方法,考虑把在这些组合对象组成的集合上进行的操作,变成在 GF 上进行的操作,从而大大提升效率。一般地,我们定义组合类:
( A , | ⋅ | ) ( A , | ⋅ | )
其中 A A 为组合对象组成的集合,| ⋅ | | ⋅ | 是一个单元操作,把一个组合对象映射为一个非负整数。举个例子,比如对于一棵树,我们关心它的结点数,所以就定义 | t | | t | 为 t t 这棵树的结点数量。我们定义 A n = { α ∈ A | | α | = n } A n = { α ∈ A | | α | = n } 。
对于组合类 ( A , | ⋅ | ) ( A , | ⋅ | ) ,其对应的 OGF 为:
A ( z ) = ∑ α ∈ A z | α | = ∑ n ≥ 0 a n z n A ( z ) = ∑ α ∈ A z | α | = ∑ n ≥ 0 a n z n
对应的 EGF 为:
^ A ( z ) = ∑ α ∈ A z | α | | α | ! = ∑ n ≥ 0 a n z n n ! A ^ ( z ) = ∑ α ∈ A z | α | | α | ! = ∑ n ≥ 0 a n z n n !
其中 a n = card ( A n ) a n = card ( A n ) ,card card 表示集合的基数。一般来说,OGF 用于无标号的情况,EGF 用于有标号的情况。
定义中性对象 ϵ ϵ 满足 | ϵ | = 0 | ϵ | = 0 ,和中性集合 E = { ϵ } E = { ϵ } ,其对应的 OGF,EGF 为:
E ( z ) = ^ E ( z ) = 1 E ( z ) = E ^ ( z ) = 1
定义原子对象 ∘ ∘ 满足 | ∘ | = 1 | ∘ | = 1 ,和原子集合 Z = { ∘ } Z = { ∘ } ,其对应的 OGF,EGF 为:
Z ( z ) = ^ Z ( z ) = z Z ( z ) = Z ^ ( z ) = z
显然我们能得到结论,∀ A ∀ A ,都有 A ≅ A × E ≅ E × A A ≅ A × E ≅ E × A ,其中我们称两个组合集 A , B A , B 满足 A ≅ B A ≅ B 当且仅当它们不平凡同构。
无标号
本部分介绍的所有操作是基于无标号的,所以对应的 GF 均采用 OGF。
不相交并
对于两个组合类的并 A , B A , B ,如果我们单纯将它记为:
A + B A + B
即简单的拼接,如果 A ∩ B ≠ ∅ A ∩ B ≠ ∅ ,就会与不相交的前提相违背。所以我们把它记为:
( E 1 × A ) + ( E 2 × B ) ( E 1 × A ) + ( E 2 × B )
即给两个乘上不同的中性对象,不改变集合的元素本质,但给它们“染上了颜色”,从而不管是否有 A ∩ B = ∅ A ∩ B = ∅ ,都可以直接拼接。而对应的 OGF 为:
A ( z ) + B ( z ) = ∑ α ∈ A z | α | + ∑ β ∈ B z | β | = ∑ n ≥ 0 ( a n + b n ) z n A ( z ) + B ( z ) = ∑ α ∈ A z | α | + ∑ β ∈ B z | β | = ∑ n ≥ 0 ( a n + b n ) z n
即两个集合对应 OGF 的幂级数加法。
笛卡尔积
我们定义两个集合的笛卡尔积 A × B A × B 为:
A × B = { ( α , β ) | α ∈ A , β ∈ B } A × B = { ( α , β ) | α ∈ A , β ∈ B }
其中如果 γ = ( α 1 , α 2 , ⋯ , α n ) γ = ( α 1 , α 2 , ⋯ , α n ) ,则我们记 | γ | = | α 1 | + | α 2 | + ⋯ + | α n | | γ | = | α 1 | + | α 2 | + ⋯ + | α n | 。通过定义可以找到对应的 OGF:
A ( z ) B ( z ) = ∑ ( α , β ) ∈ ( A × B ) z | α | + | β | = ∑ n ≥ 0 ∑ i + j = n a i b j z n A ( z ) B ( z ) = ∑ ( α , β ) ∈ ( A × B ) z | α | + | β | = ∑ n ≥ 0 ∑ i + j = n a i b j z n
即两个集合对应 OGF 的集合幂级数乘法。
序列构造
我们定义一个集合的序列构造 SEQ ( C ) SEQ ( C ) 为:
SEQ ( C ) = { ϵ } + C + C 2 + C 3 + ⋯ SEQ ( C ) = { ϵ } + C + C 2 + C 3 + ⋯
其中为了保证构造出的集合合理,必须有 C 0 = ∅ C 0 = ∅ 。感性理解就是在这个集合里选 0 0 个的方案,选 1 1 个的方案,选 2 2 个的方案等等的并,且选择组成的是序列,即顺序有所谓。对应的 OGF 为:
SEQ ( C ( z ) ) = ∑ n ≥ 0 C n ( z ) = 1 1 − C ( z ) SEQ ( C ( z ) ) = ∑ n ≥ 0 C n ( z ) = 1 1 − C ( z )
循环构造
我们定义一个集合的循环构造 CYC ( B ) CYC ( B ) 为:
CYC ( B ) = SEQ ( B ) / S CYC ( B ) = SEQ ( B ) / S
其中 S S 为一个等价关系,表示二者循环同构,/ S / S 表示把原集合按照在这个等价意义下等价的元素剔除。感性理解就是在 SEQ ( B ) SEQ ( B ) 的集合中,去掉循环同构的序列。其对应的 OGF 不那么显然,根据 OI wiki,式子是:
CYC ( B ( z ) ) = ∑ n ≥ 1 φ ( n ) n ln 1 1 − B ( z n ) CYC ( B ( z ) ) = ∑ n ≥ 1 φ ( n ) n ln 1 1 − B ( z n )
其中 φ φ 为欧拉函数。
可重集构造
我们定义一个集合的可重集构造 MSET ( A ) MSET ( A ) 为:
MSET ( A ) = SEQ ( A ) / R MSET ( A ) = SEQ ( A ) / R
其中 R R 为一个等价关系,表示两个序列对应同一个可重集,/ R / R 表示把原集合按照该等价关系相同的元素剔除。感性来看就是在序列构造的基础上,要求组成的是可重集,即顺序无所谓。除定义外,我们还能得到这样的递推式:
MSET ( { α 0 , α 1 , ⋯ α n } ) = MSET ( { α 0 , α 1 , ⋯ α n − 1 } ) × SEQ ( { α n } ) MSET ( { α 0 , α 1 , ⋯ α n } ) = MSET ( { α 0 , α 1 , ⋯ α n − 1 } ) × SEQ ( { α n } )
表示在原有的生成的可重集内,每个都加入若干个 α n α n 。更进一步,我们能发现:
MSET ( A ) = ∏ α ∈ A SEQ ( { α } ) MSET ( A ) = ∏ α ∈ A SEQ ( { α } )
因为 SEQ SEQ 对应的 OGF 已知,所以 MSET MSET 对应的 OGF 为:
MSET ( A ( z ) ) = ∏ α ∈ A ( 1 − z | α | ) − 1 = ∏ n ≥ 1 ( 1 − z n ) − a n MSET ( A ( z ) ) = ∏ α ∈ A ( 1 − z | α | ) − 1 = ∏ n ≥ 1 ( 1 − z n ) − a n
不要忘了 SEQ SEQ 要求不能出现大小为 0 0 的元素。
进一步地,我们还能通过取对数继续化简这个 OGF(具体过程可以参考我的 一篇题解 ):
MSET ( A ( z ) ) = exp ( ∑ n ≥ 1 A ( z n ) n ) MSET ( A ( z ) ) = exp ( ∑ n ≥ 1 A ( z n ) n )
可重集构造又被称作 Euler 变换。
幂集构造
我们定义一个集合的幂集构造 PSET ( B ) PSET ( B ) 为其所有子集的并。有递推式:
PSET ( { β 0 , β 1 , ⋯ , β n } ) = PSET ( { β 0 , β 1 , ⋯ , β n − 1 } ) × ( { ϵ , β n } ) PSET ( { β 0 , β 1 , ⋯ , β n } ) = PSET ( { β 0 , β 1 , ⋯ , β n − 1 } ) × ( { ϵ , β n } )
即剩下一个元素可以选,也可以不选。进一步地,我们有:
PSET ( B ) = ∏ β ∈ B ( { ϵ , β } ) PSET ( B ) = ∏ β ∈ B ( { ϵ , β } )
对应的 OGF 为:
PSET ( B ( z ) ) = ∏ β ∈ B ( 1 + z | β | ) = ∏ n ≥ 1 ( 1 + z n ) b n PSET ( B ( z ) ) = ∏ β ∈ B ( 1 + z | β | ) = ∏ n ≥ 1 ( 1 + z n ) b n
可以发现与 MSET MSET 的非常像,仅仅是换了几个符号,所以另一种 exp exp 的形式也可以类似地得出:
PSET ( B ( z ) ) = exp ( ∑ n ≥ 1 ( − 1 ) n − 1 B ( z n ) n ) PSET ( B ( z ) ) = exp ( ∑ n ≥ 1 ( − 1 ) n − 1 B ( z n ) n )
根据定义容易得到:
PSET ( B ) ⊂ MSET ( B ) PSET ( B ) ⊂ MSET ( B )
带限制的情况
上面所有的讨论都是基于不限组成部分的情况,但如果要求原序列生成的可重集个数满足某种限制——比如恰为 k k ——那就无法解决了。定义 K K 为上述 S E Q , M S E T , P S E T , C Y C S E Q , M S E T , P S E T , C Y C 的其中的一种操作,定义以下三种限制:
K ≥ l ( B ) K k ( B ) K l . . r ( B ) K ≥ l ( B ) K k ( B ) K l . . r ( B )
为组成部分大于等于 l l ,恰等于 k k ,和位于 l . . r l . . r 中。以 A = K l . . r ( B ) A = K l . . r ( B ) 为例,这要求:
∀ α ∈ A , α = { ( β 0 , β 1 , ⋯ , β k ) | β ∈ B } , l ≤ k ≤ r ∀ α ∈ A , α = { ( β 0 , β 1 , ⋯ , β k ) | β ∈ B } , l ≤ k ≤ r
考虑引入二元 GF 来解决这个问题,如果设 X ( α ) X ( α ) 表示组成 α α 的元素个数,则我们定义 A n , k A n , k 为:
A n , k = card ( { α ∈ A | | α | = n , X ( α ) = k } ) A n , k = card ( { α ∈ A | | α | = n , X ( α ) = k } )
则对应的二元 GF 为:
A ( z , u ) = ∑ n , k A n , k u k z n = ∑ α ∈ A u X ( α ) z | α | A ( z , u ) = ∑ n , k A n , k u k z n = ∑ α ∈ A u X ( α ) z | α |
容易发现,K l . . r K l . . r 的限制只需要提取出 u l . . r u l . . r 的系数,就能得到对应的 OGF,其他两个限制是类似的。
具体来看,对于 SEQ ( B ) SEQ ( B ) :
A ( z , u ) = ∑ n , k A n , k z n u k = ∑ k ≥ 0 B k ( z ) u k = 1 1 − u B ( z ) A ( z , u ) = ∑ n , k A n , k z n u k = ∑ k ≥ 0 B k ( z ) u k = 1 1 − u B ( z )
其中 A n , k z n = B k ( z ) A n , k z n = B k ( z ) 是由于对于 SEQ SEQ 构造,B ( z ) k B ( z ) k 就表示组成部分为 k k 个的 OGF。这样显然有:
[ u l ] A ( z , u ) = B l ( z ) [ u l ] A ( z , u ) = B l ( z )
对于 MSET ( B ) MSET ( B ) :
A ( z , u ) = ∏ n ( 1 − u z n ) − b n A ( z , u ) = ∏ n ( 1 − u z n ) − b n
只是给每一个元素增加了一个 u u ,表示这个元素单独的时候表示 1 1 个元素,从而两个相乘表示拼接的时候也会把 u u 的指数相加。可以用类似的方法得到 exp exp 形式:
A ( z , u ) = exp ( ∑ n ≥ 1 u n B ( z n ) n ) A ( z , u ) = exp ( ∑ n ≥ 1 u n B ( z n ) n )
把 exp exp 展开后即可提取 u l u l 的系数。
注意在这种情况下,对于 b 0 b 0 的定义很重要。如果 b 0 = 1 b 0 = 1 ,则有可能出现较多的常数项不便于计算。
对于 PSET ( B ) PSET ( B ) ,可以采用类似的思路:
A ( z , u ) = ∏ n ( 1 + u z n ) b n A ( z , u ) = ∏ n ( 1 + u z n ) b n
exp exp 形式类似:
A ( z , u ) = exp ( ∑ n ≥ 1 ( − 1 ) n − 1 u n B ( z n ) n ) A ( z , u ) = exp ( ∑ n ≥ 1 ( − 1 ) n − 1 u n B ( z n ) n )
依然是把 exp exp 展开提取系数。
一些例题
loj#6268. 分拆数
定义 f ( i ) f ( i ) 为把 i i 表示成若干正整数之和的方案数,正整数之间的顺序无所谓。求 f ( 1 ∼ 10 5 ) f ( 1 ∼ 10 5 ) ,答案对 998 , 244 , 353 998 , 244 , 353 取模。
如果我们定义组合类 ( I , | ⋅ | ) ( I , | ⋅ | ) ,其中 I = N + I = N + ,| i | = i | i | = i ,则我们发现题目里给出的分拆其实相当于:
MSET ( I ) MSET ( I )
因为不同的数组成成一个新的组合类,它的大小恰等于各个组分之和,即对于正整数的分拆,又因为顺序无所谓,所以用 MSET MSET 。具体算的方法,可以考虑把 MSET MSET 的形式展开一下:
MSET ( I ( z ) ) = exp ( ∑ n ≥ 1 I ( z n ) n ) = exp ( ∑ n ≥ 1 ∑ k ≥ 1 i k z k n n ) MSET ( I ( z ) ) = exp ( ∑ n ≥ 1 I ( z n ) n ) = exp ( ∑ n ≥ 1 ∑ k ≥ 1 i k z k n n )
这样每个 i k i k 会对所有 k k 的倍数做贡献,枚举倍数预处理出多项式就可以直接做 exp exp 了,时间复杂度 O ( n log n ) O ( n log n ) 。
int main ()
{
int n, m = 1 ; scanf ("%d" , &n); while (m <= n) m <<= 1 ;
for (int i = 1 ; i <= n; ++i)
for (int j = i; j < m; j += i) (F[j] += ksm (j / i, mod - 2 )) %= mod;
getExp (F, G, m);
for (int i = 1 ; i <= n; ++i) printf ("%d\n" , G[i]);
return 0 ;
}
洛谷 P5900 无标号无根树计数
求 n n 个点的无标号无根树数量,答案对 998244353 998244353 取模。(1 ≤ n ≤ 2 × 10 5 1 ≤ n ≤ 2 × 10 5 )
发现如果我们求的是有根树,则钦定一个根后,剩下的点其实是分成若干集合,变成子树,且各个子树又是递归结构。所以定义组合类 ( T , | ⋅ | ) ( T , | ⋅ | ) ,其中 T T 表示所有无标号有根树的集合,| t | | t | 表示这棵树结点大小,则:
T = { ∘ } × MSET ( T ) T = { ∘ } × MSET ( T )
展开成 OGF 就可以做了:
MSET ( T ( z ) ) = z exp ( ∑ n ≥ 1 T ( z n ) n ) MSET ( T ( z ) ) = z exp ( ∑ n ≥ 1 T ( z n ) n )
具体做法见我的 一篇题解 。
烷基计数 加强版 加强版
求 n n 个点的每个点度数不超过 4 4 且根的度数不超过 3 3 的有根树的数目。(1 ≤ n ≤ 10 5 1 ≤ n ≤ 10 5 )
这道题一个显然的想法是设组合类 ( T , | ⋅ | ) ( T , | ⋅ | ) ,与上一道题类似的意义,有等式:
T = { ∘ } × MSET 0..3 ( T ) T = { ∘ } × MSET 0..3 ( T )
不幸的是,如果按照这个等式进行 OGF 的展开,会得到一个非常长的式子,非常不便于计算。注意到这个等式必须要求 MSET MSET 取 0..3 0..3 是因为 T T 内没有 ϵ ϵ 元素,这样的话,满足度数 ≤ 3 ≤ 3 就必须显式表示。而如果我们定义 ^ T = T + { ϵ } T ^ = T + { ϵ } ,则会有:
^ T = { ϵ } + { ∘ } × MSET 3 ( ^ T ) T ^ = { ϵ } + { ∘ } × MSET 3 ( T ^ )
而这个式子展开就会方便很多了。考虑把 exp exp 展开:
MSET 3 ( T ( z ) ) = [ u 3 ] exp ( ∑ n ≥ 1 u n T ( z n ) n ) = [ u 3 ] ∑ i ≥ 0 ( ∑ n ≥ 1 u n T ( z n ) n ) i i ! = [ u 3 ] 1 + [ u 3 ] ( ⋯ + u 3 T ( z 3 ) 3 + ⋯ ) + [ u 3 ] ( u T ( z ) 1 + u 2 T ( z 2 ) 2 + ⋯ ) 2 2 + [ u 3 ] ( u T ( z ) 1 + ⋯ ) 3 6 = T ( z 3 ) 3 + T ( z ) T ( z 2 ) 2 + T 3 ( z ) 6 MSET 3 ( T ( z ) ) = [ u 3 ] exp ( ∑ n ≥ 1 u n T ( z n ) n ) = [ u 3 ] ∑ i ≥ 0 ( ∑ n ≥ 1 u n T ( z n ) n ) i i ! = [ u 3 ] 1 + [ u 3 ] ( ⋯ + u 3 T ( z 3 ) 3 + ⋯ ) + [ u 3 ] ( u T ( z ) 1 + u 2 T ( z 2 ) 2 + ⋯ ) 2 2 + [ u 3 ] ( u T ( z ) 1 + ⋯ ) 3 6 = T ( z 3 ) 3 + T ( z ) T ( z 2 ) 2 + T 3 ( z ) 6
这样能得到:
T ( z ) = 1 + z 6 ( 2 T ( z 3 ) + 3 T ( z ) T ( z 2 ) + T 3 ( z ) ) T ( z ) = 1 + z 6 ( 2 T ( z 3 ) + 3 T ( z ) T ( z 2 ) + T 3 ( z ) )
可以用半在线卷积或者牛顿迭代分别在 O ( n log 2 n ) O ( n log 2 n ) 和 O ( n log n ) O ( n log n ) 的时间内求解。
inline void copy (int * f, int * g, int n) { for (int i = 0 ; i < n; ++i) g[i] = f[i]; }
inline void clear (int * f, int n) { for (int i = 0 ; i < n; ++i) f[i] = 0 ; }
inline void cdq (int l, int r)
{
if (l + 1 == r) return (l % 3 == 1 ) ? ((A[l] += (ll)A[l / 3 ] * inv3 % mod) %= mod, void ()) : void ();
int mid = (l + r) >> 1 ; cdq (l, mid); init (r - l);
copy (A + l, F, mid - l); clear (F + mid - l, lim - mid + l);
copy (A, G, r - l); clear (G + r - l, lim - r + l);
for (int i = 0 ; i < lim; ++i) H[i] = 0 ;
for (int i = 0 ; i < r - l; ++i) if (!(i & 1 )) H[i] = A[i / 2 ];
NTT (F, lim, 1 ); NTT (G, lim, 1 ); NTT (H, lim, 1 );
for (int i = 0 ; i < lim; ++i)
F[i] = ((ll)F[i] * H[i] % mod * inv2 % mod + (ll)F[i] * G[i] % mod * G[i] % mod * inv2 % mod * (!l ? inv3 : 1 ) % mod) % mod;
NTT (F, lim, mod - 2 );
for (int i = mid; i < r; ++i) (A[i] += F[i - l - 1 ]) %= mod;
cdq (mid, r);
}
int main ()
{
int m; scanf ("%d" , &m); while (n <= m) n <<= 1 ; A[0 ] = 1 ;
cdq (0 , n); printf ("%d\n" , A[m]); return 0 ;
}
顺便提一句,如果按照 T = { ∘ } × MSET 0..3 ( T ) T = { ∘ } × MSET 0..3 ( T ) 展开得到的是:
T ( z ) = z 6 ( 1 + 6 T ( z ) + 3 T 2 ( z ) + 3 T ( z 2 ) + 3 T ( z ) T ( z 2 ) + 2 T ( z 3 ) + T 3 ( z ) ) T ( z ) = z 6 ( 1 + 6 T ( z ) + 3 T 2 ( z ) + 3 T ( z 2 ) + 3 T ( z ) T ( z 2 ) + 2 T ( z 3 ) + T 3 ( z ) )
如果把 T ( z ) T ( z ) 换为 T ( z ) + 1 T ( z ) + 1 ,那就跟上面那个式子一样了。所以常数项一般来说处理为 0 0 会更加方便,甚至有时候必须处理为 0 0 (比如上题无标号无根树,因为没有限制,所以一旦不处理为 0 0 ,那常数项就会爆炸)
有标号
本部分介绍的所有内容是基于有标号的,所以对应的 GF 采用 EGF。
一些有标号的例子
对于排列组成的组合类 ( P , | ⋅ | ) ( P , | ⋅ | ) ,定义 | p | | p | 为排列的长度,则其 EGF 为:
^ P ( z ) = ∑ p ∈ P z | p | | p | ! = ∑ n ≥ 0 n ! z n n ! = 1 1 − z P ^ ( z ) = ∑ p ∈ P z | p | | p | ! = ∑ n ≥ 0 n ! z n n ! = 1 1 − z
对于圆排列组成的组合类 ( C , | ⋅ | ) ( C , | ⋅ | ) ,定义 | c | | c | 为圆排列的长度,则其 EGF 为:
^ C ( z ) = ∑ c ∈ C z | c | | c | ! = ∑ n ≥ 0 ( n − 1 ) ! z n n ! = ln 1 1 − z C ^ ( z ) = ∑ c ∈ C z | c | | c | ! = ∑ n ≥ 0 ( n − 1 ) ! z n n ! = ln 1 1 − z
能看出 exp ^ C ( z ) = ^ P ( z ) exp C ^ ( z ) = P ^ ( z ) 。
对于图 G = ( V , E ) G = ( V , E ) ,且 | E | = 0 | E | = 0 ,定义其组合类 ( U , | ⋅ | ) ( U , | ⋅ | ) ,定义 | u | = | V | | u | = | V | ,则其 EGF 为:
^ U ( z ) = ∑ u ∈ U z | u | | u | ! = ∑ n ≥ 0 z n n ! = e z U ^ ( z ) = ∑ u ∈ U z | u | | u | ! = ∑ n ≥ 0 z n n ! = e z
这是由于完全没有边的图,相同大小的点集仅对应一个。
集合的有标号乘法
首先我们要知道,把两个元素做有标号乘法会有什么结果。比如 β , γ β , γ 为两个有标号元素,则我们定义二者的有标号乘法为这两个元素拼接在一起,并重新标号 。而对一个元素重新标号有两种情况,要么是把标号的值域扩大,要么缩小,这导出了对元素有标号乘法两种等价的定义:
β ∗ γ = { ( β ′ , γ ′ ) | ( β ′ , γ ′ ) 的 标 号 是 良 定 义 的 , ρ ( β ′ ) = β , ρ ( γ ′ ) = γ } β ∗ γ = { ( β ′ , γ ′ ) | ( β ′ , γ ′ ) 的 标 号 是 良 定 义 的 , ρ ( β ′ ) = β , ρ ( γ ′ ) = γ }
其中 ρ ρ 表示将标号的值域缩小后的对应。
β ∗ γ = { ( e ( β ) , f ( γ ) ) | Im ( e ) ∩ Im ( f ) = ∅ , Im ( e ) ∪ Im ( f ) = { 1 , 2 , ⋯ , | β | + | γ | } } β ∗ γ = { ( e ( β ) , f ( γ ) ) | Im ( e ) ∩ Im ( f ) = ∅ , Im ( e ) ∪ Im ( f ) = { 1 , 2 , ⋯ , | β | + | γ | } }
其中 f , e f , e 表示将标号的值域扩大后的对应,Im ( e ) Im ( e ) 表示对应到的值的集合。可能有点难理解,举个例子吧,比如将一个三角形 1 − 2 − 3 1 − 2 − 3 和一个线段 1 − 2 1 − 2 乘在一起会得到 10 10 个结果:
( 1 − 2 − 3 , 4 − 5 ) , ( 1 − 2 − 4 , 3 − 5 ) , ( 1 − 2 − 5 , 3 − 4 ) , ( 1 − 3 − 4 , 2 − 5 ) , ( 1 − 3 − 5 , 2 − 4 ) ( 1 − 4 − 5 , 2 − 3 ) , ( 2 − 3 − 4 , 1 − 5 ) , ( 2 − 3 − 5 , 1 − 4 ) , ( 2 − 4 − 5 , 1 − 3 ) , ( 3 − 4 − 5 , 1 − 2 ) ( 1 − 2 − 3 , 4 − 5 ) , ( 1 − 2 − 4 , 3 − 5 ) , ( 1 − 2 − 5 , 3 − 4 ) , ( 1 − 3 − 4 , 2 − 5 ) , ( 1 − 3 − 5 , 2 − 4 ) ( 1 − 4 − 5 , 2 − 3 ) , ( 2 − 3 − 4 , 1 − 5 ) , ( 2 − 3 − 5 , 1 − 4 ) , ( 2 − 4 − 5 , 1 − 3 ) , ( 3 − 4 − 5 , 1 − 2 )
可以观察到,两个集合 β , γ β , γ 大小分别为 n 1 , n 2 n 1 , n 2 ,如果令 n = n 1 + n 2 n = n 1 + n 2 ,则:
card ( β ∗ γ ) = ( n n 1 , n 2 ) card ( β ∗ γ ) = ( n n 1 , n 2 )
有了这个定义,我们就能得到两个集合的有标号乘法 B ∗ C B ∗ C 为:
B ∗ C = ⋃ β ∈ B , γ ∈ C ( β ∗ γ ) B ∗ C = ⋃ β ∈ B , γ ∈ C ( β ∗ γ )
对应的 EGF 操作为:
^ A ( z ) = ^ B ( z ) × ^ C ( z ) ⟺ a n = ∑ | β | + | γ | = n ( | β | + | γ | | β | , | γ | ) = ∑ n 1 + n 2 = n ( n n 1 , n 2 ) b n 1 c n 2 A ^ ( z ) = B ^ ( z ) × C ^ ( z ) ⟺ a n = ∑ | β | + | γ | = n ( | β | + | γ | | β | , | γ | ) = ∑ n 1 + n 2 = n ( n n 1 , n 2 ) b n 1 c n 2
其中:
( n n 1 , n 2 , ⋯ , n k ) = n ! n 1 ! n 2 ! ⋯ n k ! ( n n 1 , n 2 , ⋯ , n k ) = n ! n 1 ! n 2 ! ⋯ n k !
即 EGF 的幂级数乘法。容易发现这个乘法满足结合律:
A ∗ ( B ∗ C ) = ( A ∗ B ) ∗ C A ∗ ( B ∗ C ) = ( A ∗ B ) ∗ C
序列构造
我们定义一个集合的序列构造 SEQ ( B ) SEQ ( B ) 为:
SEQ ( B ) = { ϵ } + B + B 2 + B 3 + ⋯ SEQ ( B ) = { ϵ } + B + B 2 + B 3 + ⋯
其中 B n = ( B ∗ B ∗ B ∗ ⋯ ) B n = ( B ∗ B ∗ B ∗ ⋯ ) ,共 n n 个 B B 。定义 k k 序列构造 SEQ k ( B ) SEQ k ( B ) 为:
SEQ k ( B ) = B k SEQ k ( B ) = B k
可以找到对应的 EGF:
SEQ ( ^ B ( z ) ) = 1 1 − ^ B ( z ) , SEQ k ( ^ B ( z ) ) = ^ B k ( z ) SEQ ( B ^ ( z ) ) = 1 1 − B ^ ( z ) , SEQ k ( B ^ ( z ) ) = B ^ k ( z )
SEQ SEQ 构造依然要求 B 0 = ∅ B 0 = ∅ 。
感性理解就是选取 0 , 1 , 2 , ⋯ 0 , 1 , 2 , ⋯ 个元素构成的有标号,顺序有所谓的序列。
集合构造
我们定义一个集合的集合构造 SET ( B ) SET ( B ) 为:
SET ( B ) = { ϵ } + B + SET 1 ( B ) + SET 2 ( B ) + ⋯ = ⋃ k ≥ 0 SET k ( B ) SET ( B ) = { ϵ } + B + SET 1 ( B ) + SET 2 ( B ) + ⋯ = ⋃ k ≥ 0 SET k ( B )
其中 k k 集合构造 SET k ( B ) = SEQ k ( B ) / R SET k ( B ) = SEQ k ( B ) / R ,R R 为等价关系,表示两个序列中一个是另一个的排列,/ R / R 表示去掉等价的元素。可以找到对应的 EGF:
SET k ( ^ B ( z ) ) = 1 k ! ^ B k ( z ) , SET ( ^ B ( z ) ) = ∑ k ≥ 0 1 k ! ^ B k ( z ) = exp ( ^ B ( z ) ) SET k ( B ^ ( z ) ) = 1 k ! B ^ k ( z ) , SET ( B ^ ( z ) ) = ∑ k ≥ 0 1 k ! B ^ k ( z ) = exp ( B ^ ( z ) )
注意到所有东西都是有标号的,所以所有的数都是不同的,这样的话,M S E T , P S E T M S E T , P S E T 都会对应到 SET SET ,即它们都是等价的。感性理解就是选取 0 , 1 , 2 , ⋯ 0 , 1 , 2 , ⋯ 个元素构成的有标号,顺序无所谓的序列。
循环构造
我们定义一个集合的循环构造 CYC ( B ) CYC ( B ) 为:
CYC ( B ) = { ϵ } + CYC 1 ( B ) + CYC 2 ( B ) + ⋯ = ⋃ k ≥ 0 CYC k ( B ) CYC ( B ) = { ϵ } + CYC 1 ( B ) + CYC 2 ( B ) + ⋯ = ⋃ k ≥ 0 CYC k ( B )
其中 k k 循环构造 CYC k = SEQ k / S CYC k = SEQ k / S ,S S 为等价关系,表示两个序列循环同构。这样可以找到对应的 EGF:
CYC k ( ^ B ( z ) ) = 1 k ^ B k ( z ) , CYC ( ^ B ( z ) ) = ∑ k ≥ 0 1 k ^ B k ( z ) = ln 1 1 − ^ B ( z ) CYC k ( B ^ ( z ) ) = 1 k B ^ k ( z ) , CYC ( B ^ ( z ) ) = ∑ k ≥ 0 1 k B ^ k ( z ) = ln 1 1 − B ^ ( z )
通过以上这些操作,我们可以构造出一开始举出的三个例子 U , P , S U , P , S :
P = SEQ ( Z ) , U = SET ( Z ) , C = CYC ( Z ) P = SEQ ( Z ) , U = SET ( Z ) , C = CYC ( Z )
受这个启发,可以构造出的更多操作
满射
满射,即从集合 A A 到集合 B B 的一种函数,且每个值至少用到一次。我们定义满射集合 R R 为:
R = SEQ { SET ≥ 1 ( Z ) } R = SEQ { SET ≥ 1 ( Z ) }
如果给出一个 r ≥ 1 r ≥ 1 ,我们定义 R ( r ) n R n ( r ) 为从 [ 1 ⋯ n ] [ 1 ⋯ n ] 到 [ 1 ⋯ r ] [ 1 ⋯ r ] 的满射的集合,一个例子 R ( 5 ) 9 R 9 ( 5 ) 的元素之一:
ϕ = ( 1 → 2 , 2 → 1 , 3 → 2 , 4 → 3 , 5 → 5 , 6 → 3 , 7 → 5 , 8 → 3 , 9 → 4 ) ϕ = ( 1 → 2 , 2 → 1 , 3 → 2 , 4 → 3 , 5 → 5 , 6 → 3 , 7 → 5 , 8 → 3 , 9 → 4 )
注意如果把 9 → 4 9 → 4 换为 9 → 3 9 → 3 ,ϕ ϕ 就不是个满射。此外,我们定义:
R ( r ) = ⋃ n R ( r ) n R ( r ) = ⋃ n R n ( r )
注意到 R ( r ) R ( r ) 可以用一个 r r 元组集合,且它们的并集是 A A 集合表示:
( ϕ − 1 ( 1 ) , ϕ − 1 ( 2 ) , ⋯ , ϕ − 1 ( r ) ) ( ϕ − 1 ( 1 ) , ϕ − 1 ( 2 ) , ⋯ , ϕ − 1 ( r ) )
即 B B 集合对应的 A A 集合的元素的集合,上面举的例子就是:
( { 2 } , { 1 , 3 } , { 4 , 6 , 8 } , { 9 } , { 5 , 7 } ) ( { 2 } , { 1 , 3 } , { 4 , 6 , 8 } , { 9 } , { 5 , 7 } )
这样就可以找到对应的 EGF 了:
R ( r ) = SEQ r { SET ≥ 1 ( Z ) } ⇒ ^ R ( r ) ( z ) = ( e z − 1 ) r R ( r ) = SEQ r { SET ≥ 1 ( Z ) } ⇒ R ^ ( r ) ( z ) = ( e z − 1 ) r
这样 n ! [ z n ] ^ R ( r ) = R ( r ) n n ! [ z n ] R ^ ( r ) = R n ( r ) ,二项式定理爆拆:
R ( r ) n = n ! [ z n ] r ∑ j = 0 ( r j ) ( − 1 ) j e ( r − j ) z = r ∑ j = 0 ( r j ) ( − 1 ) j ( r − j ) n R n ( r ) = n ! [ z n ] ∑ j = 0 r ( r j ) ( − 1 ) j e ( r − j ) z = ∑ j = 0 r ( r j ) ( − 1 ) j ( r − j ) n
注意到 R = SEQ ( SET ≥ 1 ( Z ) ) R = SEQ ( SET ≥ 1 ( Z ) ) ,这样可以导出:
^ R ( z ) = 1 2 − e z R ^ ( z ) = 1 2 − e z
简单推导一下:
^ R ( z ) = 1 2 1 1 − 1 2 e z = ∑ l ≥ 0 e l z 2 l + 1 R ^ ( z ) = 1 2 1 1 − 1 2 e z = ∑ l ≥ 0 e l z 2 l + 1
可以得到:
R n = n ! [ z n ] ^ R ( z ) = 1 2 ∑ l ≥ 0 l n 2 l R n = n ! [ z n ] R ^ ( z ) = 1 2 ∑ l ≥ 0 l n 2 l
分割集合
定义 S ( r ) n S n ( r ) 表示把集合 { 1 , 2 , ⋯ , n } { 1 , 2 , ⋯ , n } 分成 r r 个不相交集合的方案数,定义 S ( r ) = ⋃ n S ( r ) n S ( r ) = ⋃ n S n ( r ) ,这个组合集对应的元素为一种分割,分割的每一部分被叫做一个块。而一个分割可以被一个有标号类的集合表示(每个代表一个块),所以有:
S ( r ) = SET r { SET ≥ 1 ( Z ) } ⇒ ^ S ( r ) ( z ) = 1 r ! ( e z − 1 ) r S ( r ) = SET r { SET ≥ 1 ( Z ) } ⇒ S ^ ( r ) ( z ) = 1 r ! ( e z − 1 ) r
可以发现,S ( r ) n = 1 r ! R ( r ) n S n ( r ) = 1 r ! R n ( r ) 。从组合意义可以看出,一个 r r 分割恰好对应 r ! r ! 个 r r 满射,两个满射在分割意义下是等价的,当且仅当一个是另一个的排列。
容易发现,分割数跟第二类斯特林数有很大的关系,即:
S ( r ) n = { n r } S n ( r ) = { n r }
根据第二类斯特林数的定义可以得出。所以有:
R n = ∑ r ≥ 0 r ! { n r } , S n = ∑ r ≥ 0 { n r } R n = ∑ r ≥ 0 r ! { n r } , S n = ∑ r ≥ 0 { n r }
观察到 S n S n 其实就是贝尔数。
注意到 S = SET { SET ≥ 1 ( Z ) } S = SET { SET ≥ 1 ( Z ) } ,这样可以导出:
^ S ( z ) = e e z − 1 S ^ ( z ) = e e z − 1
简单推导一下:
^ S ( z ) = 1 e e e z = 1 e ∑ l ≥ 0 e l z l ! S ^ ( z ) = 1 e e e z = 1 e ∑ l ≥ 0 e l z l !
可以得到:
S n = n ! [ z n ] ^ S ( z ) = 1 e ∑ l ≥ 0 l n l ! S n = n ! [ z n ] S ^ ( z ) = 1 e ∑ l ≥ 0 l n l !
平面图
这个 "Alignments" 我也不知道怎么翻译好,于是就直译了。一个平面图被定义为一个良标号的圆组成的序列,定义 O O 为平面图的集合,则显然有:
O = SEQ { CYC ( Z ) } ⇒ ^ O ( z ) = 1 1 − ln ( 1 − z ) − 1 O = SEQ { CYC ( Z ) } ⇒ O ^ ( z ) = 1 1 − ln ( 1 − z ) − 1
排列
注意到一个排列其实就是若干圆排列的集合,可以从置换环的角度考虑,这样排列的集合 P P 就有:
P = SET { CYC ( Z ) } ≅ SEQ ( Z ) P = SET { CYC ( Z ) } ≅ SEQ ( Z )
能导出 EGF:
^ P ( z ) = exp ( ln 1 1 − z ) = 1 1 − z P ^ ( z ) = exp ( ln 1 1 − z ) = 1 1 − z
接下来就用刚刚的方法推导一些东西吧。
树
树分为两种,一种是平面树,特点是子树之间有顺序,另一种是非平面树,特点是子树之间无顺序。此外,我们定义集合 Ω ∈ N Ω ∈ N 为树的所有点的出度的集合,其中因为树有叶子,所以一定有 0 ∈ Ω 0 ∈ Ω 。
对于平面有根树,本质上就是确定根之后,剩下的点分成若干部分变成子树,然后递归下去,所以对于平面有根树的集合 A A 有:
A = Z ∗ SEQ Ω ( A ) A = Z ∗ SEQ Ω ( A )
这样对应的 EGF 为:
^ A ( z ) = z ∑ w ∈ Ω ^ A w ( z ) A ^ ( z ) = z ∑ w ∈ Ω A ^ w ( z )
容易发现这个和不带标号的平面有根树很像,具体来讲,不带标号的平面有根树个数为:
1 n ! A n 1 n ! A n
原因根据组合意义显然。而根据我不会的拉格朗日反演可以得到:
A n = n ! [ z n ] ^ A ( z ) = ( n − 1 ) ! [ u n − 1 ] ( ∑ w ∈ Ω u w ) n A n = n ! [ z n ] A ^ ( z ) = ( n − 1 ) ! [ u n − 1 ] ( ∑ w ∈ Ω u w ) n
而对于非平面有根树,思路类似,对于它的集合 T T ,我们有:
T = Z ∗ SET Ω ( T ) T = Z ∗ SET Ω ( T )
这样对应的 EGF 为:
^ T ( z ) = z ∑ w ∈ Ω ^ T w ( z ) w ! T ^ ( z ) = z ∑ w ∈ Ω T ^ w ( z ) w !
注意到如果 Ω = N Ω = N ,则有:
^ T ( z ) = z e ^ T ( z ) T ^ ( z ) = z e T ^ ( z )
可与通过我不会的拉格朗日反演得到:
T n = n n − 1 T n = n n − 1
如果我们考虑森林,其实就是把若干个树组成一个森林,且顺序无所谓,所以森林的集合 F F 为:
F = SET { T } F = SET { T }
即 ^ F ( z ) = exp ^ T ( z ) F ^ ( z ) = exp T ^ ( z ) 。
写在最后
本篇文章参考 Analytic Combinatorics 这本书的第一,二章,对原文内容做了很大简化,有需要的同学可以找来原书看。由于本人数学很差,所以如果有错还请请喷并指出qwq
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】