Zscoder‘s 生成函数教程(三)
本文翻译自 zscoder 的 CF Blog 文章 [Tutorial] Generating Functions in Competitive Programming (Part 2) 。
本文是原文的第二部分,生成函数在 CP 中实战。
如有侵权,联系作者将尽快删除;如有翻译不足之处,敬请指出。
注意:除非有特殊情况,我们都是在模 998244353 998244353 998244353 的意义下计算。 [ n ] [n] [n] 指的是集合 { 1 , 2 , 3 , … , n } \{1,2,3,\ldots,n\} {1,2,3,…,n} 。
显然的计数问题
问题。 AGC 005 Problem F。
首先,我们需要做一个基础计数。对于一个顶点集 S S S ,令 t ( S ) t(S) t(S) 为包含 S S S 的最小的子树。
固定 k k k 的情况下如何计算 f ( S ) f(S) f(S) 呢?如果我们单独看一个顶点 v v v ,计算有多少个大小为 k k k 的 S S S 满足 t ( S ) t(S) t(S) 包含 v v v 是比较困难的。然而,我们单独的看一个边 e e e ,计算有多少个大小为 k k k 的 S S S 满足 t ( S ) t(S) t(S) 包含 e e e 是相对简单的。我们只需要删去 e e e 然后在两个连通分量中选择 k k k 个节点,这些节点的 t ( S ) t(S) t(S) 是一定包含 e e e 的。换句话说,如果我们删除 e e e 那么整棵树就变成了两个大小分别为 a a a 和 n − a n-a n−a 的连通分量,我们计算 ∑ e ∈ E ( n k ) − ( a k ) − ( n − a k ) \sum_{e \in E} \binom{n}{k} - \binom{a}{k} - \binom{n-a}{k} ∑e∈E(kn)−(ka)−(kn−a) ,这些是 t ( S ) , ∣ S ∣ = k t(S),|S| = k t(S),∣S∣=k 中所有边的数量,又因为在树中点的数量等于边的数量加一,因此 a n s k = ( n k ) + ∑ e ∈ E ( n k ) − ( a k ) − ( n − a k ) {ans}_k = \binom{n}{k} + \sum_{e \in E} \binom{n}{k} - \binom{a}{k} - \binom{n-a}{k} ansk=(kn)+∑e∈E(kn)−(ka)−(kn−a) 。
通过dfs,我们能计算出所有的 a a a ,记为 a 1 , a 2 , … , a n − 1 a_1,a_2,\ldots,a_{n-1} a1,a2,…,an−1 。如果我们能快速计算出对于所有 1 ≤ k ≤ n 1 \le k \le n 1≤k≤n 和式 ∑ i = 1 n − 1 ( a i k ) \sum_{i=1}^{n-1} \binom{a_i}{k} ∑i=1n−1(kai) 的值,那我们的问题就解决了。
我们使用一个小技巧,令 c i c_i ci 为 i i i 出现在 a 1 , a 2 , … , a n − 1 a_1,a_2,\ldots,a_{n-1} a1,a2,…,an−1 中的次数,那么我们所求为 ∑ i = 0 n c i ( i k ) \sum_{i=0}^{n} c_i \binom{i}{k} ∑i=0nci(ki) 。
接下来使用一个打开组合数的一个套路:
∑ i = 0 n c i ( i k ) = ∑ i = 0 n c i i ! k ! ( i − k ) ! = 1 k ! ∑ i = 0 n i ! c i 1 ( i − k ) ! \sum_{i=0}^{n} c_i \binom{i}{k} = \sum_{i=0}^{n} c_i \frac{i!}{k!(i-k)!} = \frac{1}{k!} \sum_{i=0}^{n} i!c_i \frac{1}{(i-k)!} i=0∑nci(ki)=i=0∑ncik!(i−k)!i!=k!1i=0∑ni!ci(i−k)!1
显然,我们只需要知道如何对于所有的 k k k 快速计算 ∑ i = 0 n i ! c i 1 ( i − k ) ! \sum_{i=0}^{n} i!c_i \frac{1}{(i-k)!} ∑i=0ni!ci(i−k)!1 。如果你学过生成函数,这非常像两个生成函数的卷积。我们引入 F ( x ) = ∑ i ≥ 0 f ( i ) x i F(x) = \sum_{i \ge 0} f(i)x^i F(x)=∑i≥0f(i)xi 和 G ( x ) = ∑ i ≥ 0 g ( i ) x i G(x) = \sum_{i \ge 0} g(i)x^i G(x)=∑i≥0g(i)xi 。
那么 C ( x ) = ∑ k ≥ 0 x k ∑ i = 0 n i ! c i 1 ( i − k ) ! = ∑ k ≥ 0 x k ∑ i = 0 n f ( i ) g ( k − i ) = F ( x ) G ( x ) C(x) = \sum_{k \ge 0}x^k \sum_{i=0}^{n} i!c_i \frac{1}{(i-k)!} = \sum_{k \ge 0}x^k \sum_{i=0}^{n} f(i)g(k-i) = F(x)G(x) C(x)=∑k≥0xk∑i=0ni!ci(i−k)!1=∑k≥0xk∑i=0nf(i)g(k−i)=F(x)G(x) 。
显然,我们令 f ( i ) = i ! c i f(i) = i!c_i f(i)=i!ci 而 g ( i ) = 1 ( − i ) ! g(i) = \frac{1}{(-i)!} g(i)=(−i)!1 ,然而当 i > 0 i \gt 0 i>0计算 ( − i ) ! (-i)! (−i)! 是没有意义的。问题不大,我们只需要平移我们的生成函数,让 x − i x^{-i} x−i 部分移动至 x n − i x^{n-i} xn−i 。此时,当我们想获取原生成函数的 x k x^k xk 次项系数的时候,我们需要获取新生成函数的 x k + n x^{k+n} xk+n 次项。
遇到卷积问题通常使用生成函数和多项式求解,然而生成函数的强大远不及此。
问题。 CF438 E
这在六年前是一道 3100 分的题目,但是现在你已经在2020年知道了多项式算法(这个年代多项式算法已经非常普及),那就非常简单了。
首先,显然的构造 f s f_s fs 是我们对于 s s s 的答案,令 F ( x ) F(x) F(x) 为 f s f_s fs 的 OGF 。
显然, f 0 = 1 f_0 = 1 f0=1 。对于 s > 0 s \gt 0 s>0 我们模仿 Catalan 数找到一个递归式:
f s = ∑ c ∈ C ∑ i ≥ 0 f i f s − c − i f_s = \sum_{c \in C} \sum_{i \ge 0}f_if_{s-c-i} fs=c∈C∑i≥0∑fifs−c−i
用生成函数的语言表达,就是:
∑ s ≥ 1 f s x s = ∑ s ≥ 1 ∑ c ∈ C x c ∑ i ≥ 0 f i x i f s − c − i x s − c − i \sum_{s \ge 1} f_s x^s = \sum_{s \ge 1}\sum_{c \in C} x^c \sum_{i \ge 0}f_ix^if_{s-c-i}x^{s-c-i} s≥1∑fsxs=s≥1∑c∈C∑xci≥0∑fixifs−c−ixs−c−i
令 F ( x ) = ∑ s ≥ 0 f s x s F(x) = \sum_{s \ge 0} f_s x^s F(x)=∑s≥0fsxs 和 C ( x ) = ∑ c ∈ C x c C(x) = \sum_{c \in C} x^c C(x)=∑c∈Cxc 那么上面的式子不就是:
F ( x ) − 1 = F ( x ) 2 C ( x ) F(x) - 1 = F(x)^2 C(x) F(x)−1=F(x)2C(x)
解这个二次方程得到 F ( x ) = 1 ± 1 − 4 C ( x ) 2 C ( x ) F(x) = \frac{1 \pm \sqrt{1-4C(x)}}{2C(x)} F(x)=2C(x)1±1−4C(x) ,当 x → 0 x \to 0 x→0 的时候, F ( x ) → 1 F(x) \to 1 F(x)→1 使用洛必达法则确定符号为负号,因此 F ( x ) = 1 − 1 − 4 C ( x ) 2 C ( x ) F(x) = \frac{1 - \sqrt{1-4C(x)}}{2C(x)} F(x)=2C(x)1−1−4C(x) 。
到这里我们基本就做完了,但是还有个实现上的细节。我们知道 C ( x ) C(x) C(x) 的常数项为 0 0 0 这代表 C ( x ) C(x) C(x) 没有逆元。我们对上面的式子进行分子有理化:
F ( x ) = 1 − 1 − 4 C ( x ) 2 C ( x ) = ( 1 − 1 − 4 C ( x ) ) ( 1 + 1 − 4 C ( x ) ) 2 C ( x ) ( 1 + 1 − 4 C ( x ) ) = 4 C ( x ) 2 C ( x ) ( 1 + 1 − 4 C ( x ) ) = 2 1 + 1 − 4 C ( x ) F(x) = \frac{1 - \sqrt{1-4C(x)}}{2C(x)} = \frac{(1 - \sqrt{1-4C(x)})(1 + \sqrt{1-4C(x)})}{2C(x)(1 + \sqrt{1-4C(x)})} = \frac{4C(x)}{2C(x)(1 + \sqrt{1-4C(x)})} = \frac{2}{1 + \sqrt{1-4C(x)}} F(x)=2C(x)1−1−4C(x)=2C(x)(1+1−4C(x))(1−1−4C(x))(1+1−4C(x))=2C(x)(1+1−4C(x))4C(x)=1+1−4C(x)2
我们要计算前 m m m 项,因此使用多项式算法的时间复杂度为 O ( m log m ) O(m \log m) O(mlogm) 。
实话说,也不能说这个题简单因为主要的难点在于计算多项式的平方根和多项式的倒数,这在6年前很少有人知道,但是在现在你可以在网上找到大量多项式的板子,我们只需要思考问题本身。
问题。 Simple Counting
这道题有一个 O ( n 2 k ) O(\frac{n^2}{k}) O(kn2) 的 DP 算法(试一试),但是无法通过这道题目。我们需要使用生成函数。令 f ( n ) f(n) f(n) 是我们的答案( k k k 是固定的)。
关键的思想就在于“恰好”条件是困难的,而“至少”条件是简单的。令 f ( S ) f(S) f(S) 指的是恰好只在点集 S S S 处下降的排列数量。而 g ( S ) g(S) g(S) 是在点集 S S S 的任意子集处下降的排列数量。显然 g ( S ) = ∑ T ∈ S f ( T ) g(S) = \sum_{T \in S}f(T) g(S)=∑T∈Sf(T) 。使用容斥原理,我们能得到 f ( S ) = ∑ T ⊆ S ( − 1 ) ∣ S ∣ − ∣ T ∣ g ( T ) f(S) = \displaystyle\sum_{T \subseteq S}(-1)^{|S| - |T|}g(T) f(S)=T⊆S∑(−1)∣S∣−∣T∣g(T) 。
g ( S ) g(S) g(S) 实际上更好计数。假设 S = { s 1 , s 2 , … , s m } S=\{s_1,s_2,\ldots,s_m\} S={s1,s2,…,sm} 在这里 s i < s i + 1 s_i \lt s_{i+1} si<si+1 。一个更好的理解就是将整个排列分成 m m m 块上升的块。这等于将 n n n 个元素分成 m m m 类,也就是 1 s 1 ! ( s 2 − s 1 ) ! ( s 3 − s 2 ) ! . . . ( n − s m ) ! \frac{1}{s_{1}!(s_{2}-s_{1})!(s_{3}-s_{2})!...(n-s_{m})!} s1!(s2−s1)!(s3−s2)!...(n−sm)!1 。因此 g ( S ) = n ! s 1 ! ( s 2 − s 1 ) ! ( s 3 − s 2 ) ! . . . ( n − s m ) ! g(S) = \frac{n!}{s_{1}!(s_{2}-s_{1})!(s_{3}-s_{2})!...(n-s_{m})!} g(S)=s1!(s2−s1)!(s3−s2)!...(n−sm)!n! 。
为了简单,我们令 D = k , 2 k , 3 k , … ∩ [ n − 1 ] D = k,2k,3k,\ldots \cap [n-1] D=k,2k,3k,…∩[n−1] 。我们需要计算 f ( D ) f(D) f(D) 。
任何的 D D D 的子集 T = { s 1 , s 2 , … , s m − 1 } T=\{s_1,s_2,\ldots,s_{m-1}\} T={s1,s2,…,sm−1} (以升序排列)能够描述为 b 1 , b 2 , … , b m b_1,b_2,\ldots,b_m b1,b2,…,bm 其中 b i = s i − s i − 1 b_i = s_i - s_{i-1} bi=si−si−1 。特别的 s 0 = 0 , s m = n s_0=0,s_m=n s0=0,sm=n 指的是每一块的大小。将 g ( T ) g(T) g(T) 化简为 G ( T ) = n ! b 1 ! b 2 ! … b m ! G(T) = \frac{n!}{b_1!b_2!\ldots b_m!} G(T)=b1!b2!…bm!n! 。
因此:
f ( D ) = ∑ T ⊆ D ( − 1 ) ∣ D ∣ − ∣ T ∣ g ( T ) = ∑ ∑ b i = n , b i good ( − 1 ) ∣ D ∣ − ( m − 1 ) n ! b 1 ! b 2 ! . . . b m ! f(D) = \displaystyle\sum_{T \subseteq D}(-1)^{|D| - |T|}g(T) = \displaystyle\sum_{\sum b_{i} = n, b_{i} \text{ good}}(-1)^{|D|-(m-1)}\frac{n!}{b_{1}!b_{2}!...b_{m}!} f(D)=T⊆D∑(−1)∣D∣−∣T∣g(T)=∑bi=n,bi good∑(−1)∣D∣−(m−1)b1!b2!...bm!n!
为了表示简单,我们将长度 n n n 表示为 k q + r kq+r kq+r 的这种形式,注意因为当 n n n 是 k k k 的倍数的时候位置 n n n 不应该考虑,因此 1 ≤ r ≤ k 1 \le r \le k 1≤r≤k 。我们使用 EGF。
F ( x ) = ∑ q ≥ 0 f ( k q + r ) ( k q + r ) ! x k q + r F(x) = \sum_{q \ge 0} \frac{f(kq+r)}{(kq+r)!}x^{kq+r} F(x)=q≥0∑(kq+r)!f(kq+r)xkq+r
= ∑ q ≥ 0 ∑ m ≥ 1 ∑ ∑ b i = k q + r , b i good ( − 1 ) q − m + 1 ( k q + r ) ! b 1 ! b 2 ! . . . b m ! ⋅ x k q + r ( k q + r ) ! = \displaystyle\sum_{q \ge 0}\displaystyle\sum_{m \ge 1}\displaystyle\sum_{\sum b_{i} = kq+r, b_{i} \text{ good}}(-1)^{q-m+1}\frac{(kq+r)!}{b_{1}!b_{2}!...b_{m}!} \cdot \frac{x^{kq+r}}{(kq+r)!} =q≥0∑m≥1∑∑bi=kq+r,bi good∑(−1)q−m+1b1!b2!...bm!(kq+r)!⋅(kq+r)!xkq+r
= ∑ m ≥ 1 ∑ q ≥ 0 ∑ ∑ b i = k q + r , b i good ( − 1 ) q − m + 1 x b 1 ⋅ x b 2 ⋅ . . . ⋅ x b m b 1 ! b 2 ! . . . b m ! = \displaystyle\sum_{m \ge 1}\displaystyle\sum_{q \ge 0}\displaystyle\sum_{\sum b_{i} = kq+r, b_{i} \text{ good}}(-1)^{q-m+1}\frac{x^{b_{1}} \cdot x^{b_{2}} \cdot ... \cdot x^{b_{m}}}{b_{1}!b_{2}!...b_{m}!} =m≥1∑q≥0∑∑bi=kq+r,bi good∑(−1)q−m+1b1!b2!...bm!xb1⋅xb2⋅...⋅xbm
= ∑ m ≥ 1 ( ∑ i ≥ 1 ( − 1 ) i − 1 ⋅ x k i ( k i ) ! ) m − 1 ⋅ ( ∑ i ≥ 0 ( − 1 ) i ⋅ x k i + r ( k i + r ) ! ) = \displaystyle\sum_{m \ge 1}\displaystyle\left(\displaystyle\sum_{i \ge 1}\frac{(-1)^{i-1} \cdot x^{ki}}{(ki)!}\right)^{m-1} \cdot \left(\displaystyle\sum_{i \ge 0}\frac{(-1)^{i} \cdot x^{ki+r}}{(ki+r)!}\right) =m≥1∑(i≥1∑(ki)!(−1)i−1⋅xki)m−1⋅(i≥0∑(ki+r)!(−1)i⋅xki+r)
花一点时间理解一些最后一个卷积。我们卷 m − 1 m-1 m−1 次整区间,最后一次卷积包含 r r r 。
继续化简我们得到:
= ( ∑ i ≥ 0 ( − 1 ) i ⋅ x k i + r ( k i + r ) ! ) ⋅ ∑ m ≥ 1 ( ∑ i ≥ 1 ( − 1 ) i − 1 ⋅ x k i ( k i ) ! ) m − 1 = \left(\displaystyle\sum_{i \ge 0}\frac{(-1)^{i} \cdot x^{ki+r}}{(ki+r)!}\right) \cdot \displaystyle\sum_{m \ge 1}\displaystyle\left(\displaystyle\sum_{i \ge 1}\frac{(-1)^{i-1} \cdot x^{ki}}{(ki)!}\right)^{m-1} =(i≥0∑(ki+r)!(−1)i⋅xki+r)⋅m≥1∑(i≥1∑(ki)!(−1)i−1⋅xki)m−1
= ( ∑ i ≥ 0 ( − 1 ) i ⋅ x k i + r ( k i + r ) ! ) ⋅ 1 1 − ( ∑ i ≥ 1 ( − 1 ) i − 1 ⋅ x k i ( k i ) ! ) = \left(\displaystyle\sum_{i \ge 0}\frac{(-1)^{i} \cdot x^{ki+r}}{(ki+r)!}\right) \cdot \frac{1}{1 - \left(\displaystyle\sum_{i \ge 1}\dfrac{(-1)^{i-1} \cdot x^{ki}}{(ki)!}\right)} =(i≥0∑(ki+r)!(−1)i⋅xki+r)⋅1−(i≥1∑(ki)!(−1)i−1⋅xki)1
= ∑ i ≥ 0 ( − 1 ) i ⋅ x k i + r ( k i + r ) ! ∑ i ≥ 0 ( − 1 ) i ⋅ x k i ( k i ) ! = \frac{\displaystyle\sum_{i \ge 0}\frac{(-1)^{i} \cdot x^{ki+r}}{(ki+r)!}}{\displaystyle\sum_{i \ge 0}\dfrac{(-1)^{i} \cdot x^{ki}}{(ki)!}} =i≥0∑(ki)!(−1)i⋅xkii≥0∑(ki+r)!(−1)i⋅xki+r
我们在 O(n \log n) 的情况下能计算出第 n n n 项,这道题就做完了。通过 EGF ,你能够消去分子中的阶乘分配分母的阶乘构造卷积。
停止时间的期望值
我认为这是生成函数另外一个绝妙的应用。最近的题目 Slime and Biscuits 就可以使用我下面介绍的这个技巧解决(题解)。让我们看一个不同的例子。
问题。 「ZJOI2019」开关
计算何时游戏结束以及计算游戏在 k k k 步时结束的概率都是比较困难的。然而,计算在 k k k 步时开关都是关状态的概率是相对好计算的。让 a ( k ) a(k) a(k) 是在 k k k 步时开关都是关状态的概率,并且令 A ( x ) A(x) A(x) 是 a ( k ) a(k) a(k) 的 EGF (接下来我们将看到我们为什么选择EGF)。
假设一个固定的数组 a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1,a2,…,an 满足 ∑ a i = k \sum a_i = k ∑ai=k 指的是开关 i i i 被按下 a i a_i ai 次。那么达到这个状态的概率是 k ! a 1 ! a 2 ! … a n ! ( p 1 S ) a 1 ( p 2 S ) a 2 … ( p n S ) a n \frac{k!}{a_1!a_2! \ldots a_n!}(\frac{p_1}{S})^{a_1} (\frac{p_2}{S})^{a_2} \ldots (\frac{p_n}{S})^{a_n} a1!a2!…an!k!(Sp1)a1(Sp2)a2…(Spn)an 。为了方便,我们让 q i = p i S q_i = \frac{p_i}{S} qi=Spi 。那么, a ( k ) k ! = q 1 a 1 a 1 ! ⋅ q 2 a 2 a 2 ! ⋅ . . . ⋅ q n a n a n ! \frac{a(k)}{k!} = \frac{q_{1}^{a_{1}}}{a_{1}!} \cdot \frac{q_{2}^{a_{2}}}{a_{2}!} \cdot ... \cdot \frac{q_{n}^{a_{n}}}{a_{n}!} k!a(k)=a1!q1a1⋅a2!q2a2⋅...⋅an!qnan 。
根据卷积,我们得到 A ( x ) = ∏ i = 1 n ( ( q i x ) 0 0 ! + ( q i x ) 2 2 ! + . . . ) A(x) = \displaystyle\prod_{i=1}^{n}\left(\frac{(q_{i}x)^{0}}{0!} + \frac{(q_{i}x)^{2}}{2!} + ...\right) A(x)=i=1∏n(0!(qix)0+2!(qix)2+...) ,因为我们需要按下开关偶数次。在一般情况下,我们的 EGF 是相似的,只不过有的开关需要按下奇数次。受这点启发,我们让 E i ( x ) = ∑ j even ( q i x ) j j ! E_{i}(x) = \displaystyle\sum_{j \text{ even}}\frac{(q_{i}x)^{j}}{j!} Ei(x)=j even∑j!(qix)j 和 O i ( x ) = ∑ j odd ( q i x ) j j ! O_{i}(x) = \displaystyle\sum_{j \text{ odd}}\frac{(q_{i}x)^{j}}{j!} Oi(x)=j odd∑j!(qix)j 。那么,如果 s i = 1 s_i = 1 si=1 我们选择 O i ( x ) O_i(x) Oi(x) 作为卷积项,反之选择 E i ( x ) E_i(x) Ei(x) 。
对于上面的式子,有一个更加压缩的形式,记得 e x + e − x 2 = cosh x = 1 + x 2 2 ! + x 4 4 ! + . . . \frac{e^{x}+e^{-x}}{2} = \cosh x = 1 + \frac{x^2}{2!} + \frac{x^4}{4!} + ... 2ex+e−x=coshx=1+2!x2+4!x4+... 。我们使用相同的思想,为了表达 E i ( x ) E_i(x) Ei(x) 和 O i ( x ) O_i(x) Oi(x) 我们也可以通过加减 exp ( q i x ) \exp(q_{i}x) exp(qix) 和 exp ( − q i x ) \exp(-q_{i}x) exp(−qix) 得到来过滤奇数次项或者偶数次项。验证表达式 O i ( x ) = exp ( q i x ) − exp ( − q i x ) 2 O_{i}(x) = \frac{\exp(q_{i}x) - \exp(-q_{i}x)}{2} Oi(x)=2exp(qix)−exp(−qix) 和 O i ( x ) = exp ( q i x ) − exp ( − q i x ) 2 O_{i}(x) = \frac{\exp(q_{i}x) - \exp(-q_{i}x)}{2} Oi(x)=2exp(qix)−exp(−qix) 。
总结一下,我们得到:
A ( x ) = ∏ i = 1 n [ exp ( q i x ) + ( − 1 ) s i exp ( − q i x ) ] 2 A(x) = \displaystyle\prod_{i=1}^{n}\frac{[\exp(q_{i}x) + (-1)^{s_{i}}\exp(-q_{i}x)]}{2} A(x)=i=1∏n2[exp(qix)+(−1)siexp(−qix)]
此时,我们可以计算出 a ( k ) a(k) a(k) 的值。让 c ( k ) c(k) c(k) 是在第 k k k 步第一次结束游戏的概率。那么 a ( k ) a(k) a(k) 和 c ( k ) c(k) c(k) 之间的关系是什么?这就是这个题目的技巧。考虑任意一个 k k k 步的操作序列,枚举第 i i i 步是我们第一次游戏结束的位置。对于前 i i i 步我们可以通过 a ( i ) a(i) a(i) 计算概率,对于后 k − i k - i k−i 步我们需要对每一个按钮都需要按下偶数次,这是 a ( k − i ) a(k - i) a(k−i) 的一个特殊情况,我们记作 b ( k − i ) b(k - i) b(k−i) 。因此, a ( k ) = ∑ i = 0 k c ( i ) b ( k − i ) a(k) = \displaystyle\sum_{i=0}^{k}c(i)b(k-i) a(k)=i=0∑kc(i)b(k−i) 。这是一个 OGF 卷积。
首先,我们先计算 b ( k ) b(k) b(k) 的 EGF。这是一个当 s i = 0 s_i = 0 si=0 的 a ( k ) a(k) a(k) 的特殊情况,我们得到:
B ( x ) = ∏ i = 1 n [ exp ( q i x ) + exp ( − q i x ) ] 2 B(x) = \displaystyle\prod_{i=1}^{n}\frac{[\exp(q_{i}x) + \exp(-q_{i}x)]}{2} B(x)=i=1∏n2[exp(qix)+exp(−qix)]
其次,我们导出 c ( k ) c(k) c(k) ,注意到上面的卷积式子,可以写作 C o ( x ) = A o ( x ) B o ( x ) C_o(x) = \frac{A_o(x)}{B_o(x)} Co(x)=Bo(x)Ao(x) 在这里 A o ( x ) A_o(x) Ao(x) B o ( x ) B_o(x) Bo(x) 和 C o ( x ) C_o(x) Co(x) 都分别是原数列的 OGF 。
我们的答案是 ∑ k = 0 ∞ k c ( k ) \displaystyle\sum_{k=0}^{\infty}kc(k) k=0∑∞kc(k) 。这其实就是 C o ′ ( 1 ) C_o'(1) Co′(1) ,通过求导法则,这就是 A o ′ ( 1 ) B o ( 1 ) − A o ( 1 ) B o ′ ( 1 ) B o ( 1 ) 2 \frac{A_{o}'(1)B_{o}(1) - A_{o}(1)B_{o}'(1)}{B_{o}(1)^2} Bo(1)2Ao′(1)Bo(1)−Ao(1)Bo′(1) 。
让我们看看如何计算 A o ( x ) A_o(x) Ao(x) ,直接计算从 A ( x ) A(x) A(x) 计算是麻烦的,注意到 A ( x ) = ∏ i = 1 n [ exp ( q i x ) + ( − 1 ) s i exp ( − q i x ) ] 2 A(x) = \displaystyle\prod_{i=1}^{n}\frac{[\exp(q_{i}x) + (-1)^{s_{i}}\exp(-q_{i}x)]}{2} A(x)=i=1∏n2[exp(qix)+(−1)siexp(−qix)] 。我们可以直接展开这个式子,由于 q i = p i S q_i = \frac{p_i}{S} qi=Spi ,展开后应该形如 A ( x ) = ∑ − S S a i exp ( i S x ) A(x) = \displaystyle\sum_{-S}^{S}a_{i}\exp\left(\frac{i}{S}x\right) A(x)=−S∑Saiexp(Six) , a i a_i ai 是每一项的系数。
接下来的问题是如何快速展开式子?我们可以使用 DP,考虑 d p [ i ] [ j ] dp[i][j] dp[i][j] 指的是展开前 i i i 项 a j a_j aj 的系数,这可以在 O ( n S ) O(nS) O(nS) 计算出来。
易得 A o ( x ) = ∑ i = − S S a i ∑ j ≥ 0 ( i S x ) j = ∑ i = − S S a i 1 − i S x A_{o}(x) = \displaystyle\sum_{i=-S}^{S}a_{i}\sum_{j \ge 0}\left(\frac{i}{S}x\right)^{j} = \displaystyle\sum_{i=-S}^{S}\frac{a_{i}}{1 - \frac{i}{S}x} Ao(x)=i=−S∑Saij≥0∑(Six)j=i=−S∑S1−Sixai 。 B o ( x ) B_o(x) Bo(x) 的计算也同理可得。
如果我们直接计算 A ( 1 ) A(1) A(1) 的话,我们会遇到一个除以 0 0 0 的麻烦,但是由于 C o ( x ) = A o ( x ) B o ( x ) C_o(x) = \frac{A_o(x)}{B_o(x)} Co(x)=Bo(x)Ao(x) ,我们可以分母分子同时乘以 1 − x 1-x 1−x ,令 E ( x ) = A o ( x ) ( 1 − x ) E(x) = A_o(x)(1-x) E(x)=Ao(x)(1−x) 和 F ( x ) = B o ( x ) ( 1 − x ) F(x) = B_o(x)(1-x) F(x)=Bo(x)(1−x) 。
E ( 1 ) E(1) E(1) 的计算是简单的,因为 ( 1 − x ) A o ( x ) = ∑ i = − S S a i ( 1 − x ) 1 − i S x = ∑ i = − S S − 1 a i ( 1 − x ) 1 − i S x + a S (1-x)A_{o}(x) = \displaystyle\sum_{i=-S}^{S}\frac{a_{i}(1-x)}{1 - \frac{i}{S}x} = \displaystyle\sum_{i=-S}^{S-1}\frac{a_{i}(1-x)}{1 - \frac{i}{S}x} + a_{S} (1−x)Ao(x)=i=−S∑S1−Sixai(1−x)=i=−S∑S−11−Sixai(1−x)+aS 。因此 E ( 1 ) = a S E(1)=a_S E(1)=aS 。
E ′ ( 1 ) E'(1) E′(1) 也不是很难,根据求导法则,我们得到:
E ′ ( x ) = [ ∑ i = − S S − 1 a i ( 1 − x ) 1 − i S x ] ′ = ∑ i = − S S − 1 − a i ( 1 − i S x ) − a i ( 1 − x ) ( − i S ) ( 1 − i S x ) 2 E'(x) = \left[\displaystyle\sum_{i=-S}^{S-1}\frac{a_{i}(1-x)}{1 - \frac{i}{S}x}\right]' = \displaystyle\sum_{i=-S}^{S-1}\frac{-a_{i}\left(1 - \frac{i}{S}x\right) - a_{i}(1-x)\left(-\frac{i}{S}\right)}{\left(1 - \frac{i}{S}x\right)^2} E′(x)=[i=−S∑S−11−Sixai(1−x)]′=i=−S∑S−1(1−Six)2−ai(1−Six)−ai(1−x)(−Si)
带入 x = 1 x = 1 x=1 得到 E ′ ( 1 ) = ∑ i = − S S − 1 − a i 1 − i S E'(1) = \displaystyle\sum_{i=-S}^{S-1}\frac{-a_{i}}{1 - \frac{i}{S}} E′(1)=i=−S∑S−11−Si−ai ,这可以在 O ( S ) O(S) O(S) 的时间内计算得到。
最后,我们能在 O ( n S ) O(nS) O(nS) 内解决这个题目。
一般情况下,构造 A A A 和 B B B 来解决停止时间问题通常是有效的,因为计算 A A A 和 B B B 不需要考虑第一次停止。