- [学习笔记 #?] Bostan-Mori 算法和 常系数齐次线性递推
- Bostan-Mori 算法
- 常系数齐次线性递推(使用此算法)
[学习笔记 #?] Bostan-Mori 算法和 常系数齐次线性递推
Bostan-Mori 算法
它本身用来求 $[x ^ k] \frac { f(x) } { g(x) } $,其中 \(f(x), g(x)\) 的次数分别为 \(n, m\),\(n, m \leq 10 ^ 5, k \leq 10 ^ 9\)。
而实际应用时,它可以用于常系数齐次线性递推。
发现 \(g(x)g(-x)\) 有一个良好的性质:由于 \(g(x)\) 和 \(g(-x)\) 的奇次项系数互为相反数,所以 \(g(x)g(-x)\) 的奇次项系数为 \(0\)。因此我们不妨把 \(g\) 这个多项式的奇数次项都去掉(这些项没有了,剩下的高次往低次挪,相当于系数全部 \(/2\)),得到多项式 \(H\),那么 \(g(x)g(-x)=H(x^2)\)。
我们考虑怎么把这个东西放到上面的式子里,于是上下同乘一个 \(g(-x)\)。现在我们要求 \([x ^ k]\frac {f(x)g(-x)} {g(x)g(-x)}\),即 \([x^k]\frac { f(x)g(-x) }{ H(x^2) }\)。我们发现上面这个东西没法用刚才的方式变化,但是我们出于两个原因仍然把它按次数奇偶划分,两个原因如下:
- 为了契合分母的变化。
- 我们要求的仅仅是一项的系数,而这一项在这一轮要么由奇数次的项贡献而来,要么由偶数次的项贡献而来(感性理解,分母只有偶数次的有值,而分子现在分成两部分,一部分只有奇数次的有值,一部分只有偶数次的有值)。
类比上面的 \(H\),把 \(f(x)g(-x)\) 拆成 \(( F(x^2) + x G(x^2) )\) 那么我们现在要求的就变成了 \([x ^ k]\frac{F(x^2)+xG(x^2)}{H(x^2)}\)。现在各个 [函数](?)里都是 \(x^2\) 的形式了。根据 \(k\) 的奇偶性分类讨论:
- 若 \(2 \mid k\),则答案为 \([x^{\lfloor k/2 \rfloor}]\frac{F(x)}{H(x)}\)。
- 若 \(2 \nmid k\),则答案为 \([x ^ { \lfloor k / 2 \rfloor }] \frac {G(x)} {H(x)}\)。
递归下去计算即可。边界:若 \(k = 0\),则返回常数项。
假设 \(n = m\)。不管计算常数项的时间复杂度。每次减半,那么直接写暴力多项式乘法的时间复杂度 似乎(我不太确定) 是 \(O(n^2\log k)\)。如果用 FFT 或 NTT,则时间复杂度 似乎(我不太确定) 为 \(O(n \log n \log k)\)。
看网上博客说使用限制是模数要是质数,我还不懂。
常系数齐次线性递推(使用此算法)
\(a_n = \sum _ { i = 1 } ^ k F _ i \times a _ { n - i }\),已知 \(n, k, F_{1\ldots k}, a_{0\ldots k-1}\),求 \(a_n \bmod 998244353\)。(来自洛谷上的模板题)
使用生成函数把它变成 Bostan-Mori 算法求的东西的形式,即构造函数 \(f(x),g(x)\) 使得 \(a _ n = [x^n]\frac {f(x)} {g(x)}\)。其实就是要 \(f = g a\)。
\(i\) 特别大时 \(f_i=0\),我们令 \(i \geq k\) 时 \(f_i=0\),从 \(\geq k\) 的 \(i\) 入手。
此时我们强制让 \(i > k\) 时 \(g _ i\) 也为 \(0\)。那么就有:
我们令 \(g _ 0 = 1\)。那么就有 \(a _ i = - \sum _ { j = 1 } ^ k g _ j a _ { i - j }\)。
对于 \(1 \leq i \leq k\),令 \(g _ i = - F _ i\)。
发现现在的 \(a\) 和 \(g\) 满足了递推 \(a\) 的关系。
想更简单地表示 \(g\),发现 \(g = 1 - F\),其中 \(F\) 中没给的项都认为系数为 \(0\)。
而根据前面的构造,\(f = (g a) \bmod x ^ k\),可以直接用 FFT 或 NTT 算出来。
那么现在有了 \(f,g\),直接用 Bostan-Mori 求 \(a _ n\) 即可。
\(f\) 的次数最大是 \(k - 1\),\(g\) 的次数最大是 \(k\)。在 Bostan-Mori 算法中使用 FFT 或 NTT,并且有上面 Bostan-Mori 算法的时间复杂度的条件,那么时间复杂度为 \(O(k\log k\log n)\)(我还是不太确定)。
2024.12.14