BJ United Round #3 题解

本文探讨了无标号无根树的计数方法,重点介绍了一种基于多项式迭代的高效算法,复杂度达到Θ(nlog⁡n)。文中详细解释了如何利用生成函数和Pólya计数定理优化计算过程,以及如何通过牛顿迭代解决三元三次方程。此外,还提供了多种算法策略,包括多项式快速幂、基于周期函数的表示、针对特定d值的优化方法等。

三色树

这道题的主要目的是普及无标号无根树的计数方法,故不讨论非多项式时间做法。其实 n n n 完全可以出得更大,但是没必要。

这道题改自 ProjectEuler#677

思路要点

首先考虑无标号有根树,我们只需维护 dp 数组 R ( n ) , B ( n ) , Y ( n ) R(n), B(n), Y(n) R(n),B(n),Y(n) 即可。通过更新 dp 数组 Q ( d , n ) Q(d, n) Q(d,n) 表示此时不在意节点的根的颜色,且根的度数为 d d d 即可维护红根和蓝根, W ( d , n ) W(d, n) W(d,n) 用于维护孩子没有黄根树的,这可以帮助计算黄根。每次 update 会消耗 Θ ( n ) \Theta(n) Θ(n) 的时间,比如说已经计算完了 R ( n ) R(n) R(n) 的值,那么它作为子树有可能出现了 k k k 次,则选出 ( R ( n ) + k − 1 k − 1 ) \displaystyle \binom{R(n) + k - 1}{k - 1} (k1R(n)+k1) 种方案,令 Q ( d , N ) Q(d,N) Q(d,N) 加上 ( R ( n ) + k − 1 k − 1 ) Q ( d − k , N − k n ) \binom{R(n) + k - 1}{k - 1} Q(d - k, N - kn) (k1R(n)+k1)Q(dk,Nkn)

这一部分的复杂度为 Θ ( n 2 ) \Theta(n^2) Θ(n2)

计算无标号无根树的要点是观察树的一个特殊点:一颗树要么存在唯一一个重心使得任何一个子树的大小均 < n 2 < \frac{n}2 <2n,要么存在一个“重边”使得它将树恰好分为大小为 n 2 \frac n2 2n 的两部分。

对于前者部分的计数,我们只需将 dp 数组计算到 ⌈ n 2 ⌉ − 1 \lceil \frac n2 \rceil - 1 2n1 时,将 Q , R Q,R Q,R 数组取出。对于后者,若 n n n 是偶数,当计算完 n 2 \frac n2 2n 的 dp 值时,将 R , B , Y R, B, Y R,B,Y 用于计算即可。

如何做到更快

考虑计算 R , B , Y R,B,Y R,B,Y 的生成函数 G R ( x ) , G B ( x ) , G Y ( x ) G_R(x), G_B(x), G_Y(x) GR(x),GB(x),GY(x)

我们记 S = G R + G B + G Y S = G_R + G_B + G_Y S=GR+GB+GY,我们使用 Pólya 计数定理表示 3 3 3 个孩子的树,通过枚举置换群:
S ( x ) 3 + 3 S ( x 2 ) S ( x ) + 2 S ( x 3 ) 3 ! \frac{S(x)^3 + 3S(x^2)S(x) + 2S(x^3)}{3!} 3!S(x)3+3S(x2)S(x)+2S(x3)

读者可自己尝试推导 4 4 4 2 2 2 个孩子的树。

由此我们可以通过 G R , G B , G Y G_R, G_B, G_Y GR,GB,GY 自身带入 x , x 2 , x 3 x, x^2, x^3 x,x2,x3 这些的多项式来表示。接下来考虑如何求解。

我们让 G R , G B , G Y G_R, G_B, G_Y GR,GB,GY 放在一起进行迭代,我们考虑倍增,由于已经计算出了前 n 2 \frac n2 2n 项,所有带入 x 2 , x 3 x^2, x^3 x2,x3 的部分就已经确定了,我们可以认为是常数。接下来就是一个关于 G R , G B , G Y G_R, G_B, G_Y GR,GB,GY 的三元三次方程,这依然可以通过牛顿迭代解决,也就是这等价于根据 G R , G B , G Y G_R, G_B, G_Y GR,GB,GY 的定义式得到了 3 3 3 个它们之间的关系式 E R / E B / E Y ( G R , G B , G Y ) = 0 E_R/E_B/E_Y(G_R, G_B, G_Y) = 0 ER/EB/EY(GR,GB,GY)=0,将 E R / E B / E Y ( u , v , w ) E_R/E_B/E_Y(u, v, w) ER/EB/EY(u,v,w) G R , G B , G Y G_R, G_B, G_Y GR,GB,GY 处泰勒展开就是一次方程,求解一个三元一次方程即可。

本算法的复杂度为 Θ ( n log ⁡ n ) \Theta(n\log n) Θ(nlogn)常数显而易见的大,欢迎有兴趣的同学来实现

押韵

事实上本题是 UOJ #450. 【集训队作业2018】复读机 的一个加强版。

算法一

n ≤ 5 × 1 0 4 n\le 5\times 10^4 n5×104,我可以做多项式快速幂!这个多项式就是 ( ∑ j ≥ 0 x j d ( j d ) ! ) k (\sum_{j\ge 0} \frac{x^{jd}}{(jd)!})^k (j0(jd)!xjd)k。这个模数不太友好,你可能需要 MTT……常数应该很大。

时间复杂度 Θ ( n log ⁡ n ) ∼ Θ ( n log ⁡ n log ⁡ k ) \Theta(n\log n) \sim \Theta(n\log n \log k) Θ(nlogn)Θ(nlognlogk),前者是进行多项式 ln ⁡ , exp ⁡ \ln , \exp ln,exp 达到的复杂度,但是常数可能很大。

预计得分 20 % 20\% 20%

算法二

我们考察 ( ∑ j ≥ 0 x j d ( j d ) ! ) k (\sum_{j\ge 0} \frac{x^{jd}}{(jd)!})^k (j0(jd)!xjd)k 可以如何表示。

事实上与周期函数有关的,我们可以自然想到类似 DFT 的形式,也就是考虑到 ∑ j = 0 d − 1 ω d c j = d [ d ∣ c ] \sum_{j=0}^{d - 1} \omega_d^{cj} = d[d | c] j=0d1ωdcj=d[dc],因此我们可以知道上面的那个多项式实际上是

1 d ∑ j = 0 d − 1 exp ⁡ ω d j x \frac1d \sum_{j=0}^{d-1} \exp \omega_d^j x d1j=0d1expωdjx

我们直接枚举拆括号的过程中计算了几个 exp ⁡ ω d 0 x \exp \omega_d^0 x expωd0x,几个 exp ⁡ ω d 1 x \exp \omega_d^1 x expωd1x……然后这一部分的贡献就是 ( c 0 + c 1 ω d 1 + c 2 ω d 2 + …   ) n (c_0 + c_1 \omega_d^1 + c_2 \omega_d^2 + \dots)^n (c0+c1ωd1+c2ωd2+)n。最后总和除以 d k d^k dk

时间复杂度 Θ ( k d − 1 log ⁡ n ) \Theta(k^{d-1}\log n) Θ(kd1logn),预计得分 50 % 50\% 50%

算法三

主要思想还是围绕优化计算下式:

[ x n ] ( 1 d ∑ j = 0 d − 1 exp ⁡ ω d j x ) k [x^n]\left( \frac1d \sum_{j=0}^{d-1} \exp \omega_d^j x \right)^k [xn](d1j=0d1expωdjx)k

对于 d = 4 d=4 d=4 的情况,我们实际上是只需要统计每个 exp ⁡ ( a + b i ) x \exp (a + b\mathrm{i})x exp(a+bi)x 出现多少次。通过推导一些式子,或者直接将复平面旋转 4 5 ∘ 45^\circ 45 我们可以得到,方案数是 ( k k + ∣ a + b ∣ 2 ) ( k k + ∣ a − b ∣ 2 ) \displaystyle\binom{k}{\frac{k + |a+b|}2} \binom{k}{\frac{k + |a-b|}2} (2k+a+bk)(2k+abk)。因此答案可以在 Θ ( k 2 log ⁡ n ) \Theta(k^2 \log n) Θ(k2logn) 内计算出来。

预计得分 70 % 70\% 70%

算法四

对于 d = 6 d=6 d=6 的情况,我们注意到 ω 6 \omega_6 ω6 的代数关系有 ω − 1 = ω 2 \omega - 1 = \omega^2 ω1=ω2,因此所有的根都可以用 1 , ω 1, \omega 1,ω 表示,即给每个数赋予了一个离散的二维坐标
ω 0 = 1 ω 1 = ω ω 2 = − 1 + ω ω 3 = − 1 ω 4 = − ω ω 5 = 1 + − ω \begin{array}{clclc} \omega^0 & = & 1 & & \\ \omega^1 & = & & & \omega\\ \omega^2 & = & -1 & + & \omega\\ \omega^3 & = & -1 & & \\ \omega^4 & = & & &-\omega\\ \omega^5 & = & 1 & + &-\omega \end{array} ω0ω1ω2ω3ω4ω5======1111++ωωωω
因此我们只需要做一个二维的快速幂,倍增 FFT 可以做到 Θ ( k 2 log ⁡ k ) \Theta(k^2 \log k) Θ(k2logk)。但是常数可能较大。

预计得分 80 % ∼ 100 % 80\% \sim 100\% 80%100%

算法五

考虑计算一个二元母函数的高阶幂, G ( x , y ) = F ( x , y ) k G(x, y) = F(x, y)^k G(x,y)=F(x,y)k,可以得到 F ∂ G ∂ x = k G ∂ F ∂ x F \frac{\partial G}{\partial_x} = kG \frac{\partial F}{\partial_x} FxG=kGxF,由此可列得递推式子解出所有系数。计算高阶幂的复杂度是 Θ ( k 2 ) \Theta(k^2) Θ(k2) 的。复杂度 Θ ( k 2 log ⁡ n ) \Theta(k^2 \log n) Θ(k2logn) 且常数较小。

事实上这也是可以直接用来做 k = 4 k=4 k=4 的情况的。

预计得分 100 % 100\% 100%

further

对于更大的 d d d,我们期望能得到一个怎样的做法?考虑 d d d 次单位根的代数关系,我们希望能够基于一个它们的有理系数线性组合的基。由此则能将维度缩到基的维度,在其上进行快速幂。

我将说明维度可以达到 φ ( d ) \varphi(d) φ(d),而数学迷告诉我说通过一些关于域的理论可以证明这也是下界,等我学了之后补一下证明

考虑分圆多项式 Φ d ( x ) = ∏ 0 ≤ k < d , gcd ⁡ ( d , k ) = 1 ( x − ω d k ) \Phi_d(x) = \prod_{0\le k < d, \gcd(d, k) = 1} (x - \omega_d^k) Φd(x)=0k<d,gcd(d,k)=1(xωdk),它的次数显然是 φ ( d ) \varphi(d) φ(d)

显然分圆多项式也可以用容斥原理重写,即

Φ d ( x ) = ∏ k ∣ d ( x d / k − 1 ) μ ( k ) \Phi_d(x) = \prod_{k|d} (x^{d/k}-1)^{\mu(k)} Φd(x)=kd(xd/k1)μ(k)

显然该多项式的系数都是整数。由于 Φ d ( ω d ) = 0 \Phi_d(\omega_d) = 0 Φd(ωd)=0,不难得到 ω d k = x k   m o d   Φ d ∣ x = ω \omega_d^k = \left.x^k \bmod \Phi_d\right \vert_{x=\omega} ωdk=xkmodΦdx=ω。因此这个多项式的取模自然而然地导出了每个单位根到 1 , ω d , … , ω d φ ( d ) − 1 1, \omega_d, \dots, \omega_d^{\varphi(d) - 1} 1,ωd,,ωdφ(d)1 的线性组合。

观察星象

算法一

显然所选的圆上要么有两个点要么有至少三个。因此分别枚举,枚举两个点作为圆的直径,此外枚举三个点之后可以确定唯一一个外接圆。

时间复杂度 Θ ( n 4 ) \Theta(n^4) Θ(n4),预计得分 10 % 10\% 10%

算法二

m = n m=n m=n 的情况就是经典的最小圆覆盖问题。

首先将点的顺序打乱,考虑维护前 k k k 个点的最小圆。可以证明前 k + 1 k+1 k+1 个点的最小覆盖圆由前 k k k 个点最小覆盖圆上的关键点和第 k + 1 k+1 k+1 个点,新的最小覆盖圆的关键点一定在这些点之间。因此只有常数种情况,每种通过 Θ ( n ) \Theta(n) Θ(n) 的 check 即可。第 k k k 个点不在前 k − 1 k-1 k1 个点的最小覆盖圆内的概率显然是 O ( 1 k ) O(\frac1k) O(k1),因此第 k k k 个点消耗的期望复杂度是 Θ ( k ) ⋅ O ( 1 k ) = Θ ( 1 ) \Theta(k) \cdot O(\frac1k) = \Theta(1) Θ(k)O(k1)=Θ(1)

期望时间复杂度 Θ ( n ) \Theta(n) Θ(n),预计得分 20 % 20\% 20%

算法三

我们考虑二分答案。那么接下来枚举哪个点在圆上,其它每个点我们可以计算出它对于当前圆在哪个夹角区间内,进行一遍前缀和即可查找出是否存在一个夹角使得该圆包含 m m m 个点。

时间复杂度 Θ ( n 2 log ⁡ n log ⁡ x ϵ ) \Theta(n^2\log n \log \frac{x}{\epsilon}) Θ(n2lognlogϵx),预计得分 60 % 60\% 60%

算法四

我们对算法三进行进一步的观察。事实上我们可以看成这样一个问题,对于第 i i i 个点,客观上存在一个 r i r_i ri 即最小的圆的半径使得圆内有 m m m 个点(我们认为无解即 + ∞ +\infty +),我们在二分的过程中,总共会预计调用 Θ ( n log ⁡ x ϵ ) \Theta(n\log \frac{x}{\epsilon}) Θ(nlogϵx) 次检查。这实际上是有所浪费的,在同样的检查次数内,实际上我们还可以算出每个 i i i 对应的 r i r_i ri,换句话说我们多获取了不必要的信息,因为我们只关心最小值。

接下来就是有趣的地方了:我们先将序列随机打乱,并把当前最小值设为 a = + ∞ a = +\infty a=+。接下来我们将点一个个考虑,我们实际上可以一次检查出当前点的答案是否可以 < a < a <a。如果并不小于,我们就可以略过它,否则对该点的答案进行二分。这样显然是进行 n + L log ⁡ x ϵ n + L\log \frac{x}{\epsilon} n+Llogϵx 次检查,其中 L L L r i r_i ri 序列的单调栈长度。

显然最坏情况是 r r r 互不相同时,单调栈长度的期望最长,这等价于一个排列的期望长度。而这一期望长度等于 H n = ∑ k = 1 n 1 k = Θ ( log ⁡ n ) H_n = \sum_{k=1}^n \frac 1k = \Theta(\log n) Hn=k=1nk1=Θ(logn)

因此本算法的期望复杂度为 Θ ( ( n + log ⁡ n log ⁡ x ϵ ) n log ⁡ n ) \Theta( (n + \log n \log \frac{x}{\epsilon}) n\log n) Θ((n+lognlogϵx)nlogn),预计得分 100 % 100\% 100%

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值