「笔记」多项式乱写


没什么干货,基本上都是瞎写,而且是想到什么写什么,所以可能你看完也学习不到什么。

由于我数学很差,所以可能会写大堆废话 + 大堆错误 + 大堆不带证明的结论。

对之前多项式(生成函数)相关内容做个整理,之前的垃圾博客都隐藏了。

由于我水平有限,所以写的东西比较显然,内容也十分基础入门。

大部分算法只限于口胡而没有实现过,所以不保证正确性。


GF?

按照幂级数的角度理解,敛散性(比如 \(F(x) = \sum i!x^i\) 只在 \(x = 0\) 处收敛)?

形式幂级数?\(\exp,\ln,\int,\frac{d}{dx}\) 等算子的正确性?下文牛顿迭代中所说泰勒展开的正确性?

放弃思考。


DIF & DIT

https://xyix.gitee.io/posts/?page=2&themecolor=Z&postname=dft-acceleration

一个关于 DFT 的常数优化,不需要做蝴蝶变换。


mtt

不太想再写一遍 fft 相关教程,就写个 mtt 的做法吧。

\(S = \lfloor\sqrt{M}\rfloor\),可以把系数 \(a_i\) 拆成 \(\lfloor\frac{a_i}{S}\rfloor\)\(a_i \bmod S\),这样正变换四次,逆变换三次即可,且精度也有保证。

将两次正变换缩成一次的优化:如果当前有两个实系数多项式 \(A(x), B(x)\) 要正变换,可以转化成 \(P(x)=A(x)+iB(x),Q(x) =A-iB(x)\) 正变换。

考虑知 \(Q\)\(P\)(以下记 \(\overline{z}\) 表示 \(z\) 的共轭,记 \(\hat{Q}_j\) 表示 \(Q(\omega_{n}^{j})\)):

\[\hat Q_j=\sum_{k=0}^{n-1}(a_k-ib_k)\times\omega_{n}^{jk} = \sum_{k=0}^{n-1}\overline{(a_k+ib_k)}\times\overline{\omega_{n}^{(n-j)k}} =\sum_{k=0}^{n-1}\overline{(a_k+ib_k)\times \omega_{n}^{(n-j)k}}=\overline{\hat P_{n-j}} \]

然后考虑逆变换是否也可以两次缩一次:\(\hat R_j = \hat A_j + i\hat B_j\),则逆变换后 \(r_j = a_j + ib_j\)。由于 \(A(x),B(x)\) 都是实系数,所以直接取实虚部对应系数即可。

这样的话只需做 4 次(严格来说只需做 3.5 次 —— 假如你需要做多次卷积,可以把单出来的逆变换放一起做)。


牛顿迭代

事实上,牛顿迭代一般是用来解方程的数值解而非方程的封闭解。

update:我感觉 OI 里面许多应用其实都是在求 “数值解”。

解方程 \(A(f) = 0\bmod x^n\),基础思想为倍增,即根据 \(\bmod x^n\) 的解 \(f_0\) 求出 \(\bmod x^{2n}\) 的解 \(f\)

注意到 \(f = f_0 \bmod x^n\),因此有 \((f-f_0)^2 = 0\bmod x^{2n}\),也即 \((f - f_0)^k = 0 \bmod x^{2n}, k > 1\)

考虑将 \(A(f)\)\(f_0\) 处泰勒展开得 \(A(f) = \sum_{i=0}^{\infin}\frac{A^{(i)}(f_0)}{i!}(f - f_0)^i=0\bmod x^{2n}\)

你可能会说 \(A'\) 是什么鬼。

可以理解成二元 GF \(A(x,f)\),然后求偏导 \(\frac{\partial A}{\partial f}\)

此时不难理解 \(\frac{\partial g(x)}{\partial f} = 0\),其中 \(g(x)\)\(f\) 代数无关(是否可以这么描述?存疑)。

另外 \(\frac{\partial f(x^2)}{\partial f}\) 似乎并不良定义,但是在 \(\bmod x^n\) 时可以认为 \(\frac{\partial f(x^2)}{\partial f} = 0\)

由上,\(A(f) = A(f_0) + A'(f_0)(f - f_0)=0\bmod x^{2n}\),变形得到 \(f = f_0-\frac{A(f_0)}{A'(f_0)} \bmod z^{2n}\)(牛顿迭代)。

这里的复杂度瓶颈在于计算 \(\frac{A(f_0)}{A'(f_0)}\)(实际上在做多项式复合)。


几个经典应用:

(1)求逆,即解方程 \(\frac{1}{f} - g(x) = 0\)(方程 \(g(x)f - 1 = 0\) 也正确,但需要一点 trick),牛迭式为 \(f = f_0(2 - g(x)f_0)\)

(2)求 \(\ln\)(尽管它并不是用牛迭做),\(\ln f = \int \frac{f'}{f}dz\),求逆即可。

(3)求 \(\exp\),即解方程 \(\ln f - g(x)=0\),牛迭式为 \(f = f_0(1-\ln f_0 + g(x))\)

(4)求幂,\(g^k(x) = \exp(k\times\ln g(x))\)

这里有一些问题,在模域上 \(\exp\) 并不完整(即使模质数 \(p\),在 \(p\) 项以后也不能良定义)。

如果考虑在 \(GF(p)\) 上,则 \(f^p(x) = f(x^p)\),也就是所谓的 “指数取模”(顺带一提,lucas 定理是前式的特例)。

(5)求一阶微分方程,即解方程 \(\frac{df}{dx} = A(f)\)(如 https://uoj.ac/problem/50 )。

\(\frac{df}{dx} = A(f) = A(f_0) + A'(f_0)(f-f_0)\bmod x^{2n}\)

一阶线性微分方程 \(\frac{df}{dx} - A'(f_0)f = A(f_0) - A'(f_0)f_0\bmod x^{2n}\)

那么记 \(P(f_0) = e^{\int A'(f_0)dz}\),则 \(\frac{df}{dx} - A'(f_0)f = \frac{1}{P(f_0)}\times\frac{d(P(f_0)f)}{dx}\),即可得到 \(f\)

没实现,不知道正确性。

以上例子时间复杂度都是 \(O(\sum_{i=0}\frac{n}{2^i}\log \frac{n}{2^i}) = O(n\log n)\)


带余除法

域上的多项式环是欧几里得环。

\(F(x)=\sum_{i=0}^{n-1}f_ix^i\),则记 \(degF=n-1\)

给定 \(A(x), B(x)\),我们想找到 \(P(x),R(x)\) 满足 \(degR<degB\)\(A(x)=B(x)P(x) + R(x)\)。可以发现此时有 \(degP=degA-degB\)

考虑变换 \(A_r(x) = x^{degA}A(x^{-1})\),即把 \(A\) 的系数翻转得到 \(A_r(x)\)

对上述等式做该变换得到 \(A_r(x)=B_r(x)P_r(x)+R_r(x)x^{degA-degB+1}\),对 \(x^{degA-degB+1}\) 取模转化成多项式求逆,求出 \(P(x)\) 后作减法即得 \(R(x)\)


多点求值

传统做法:

如果想对 \(x_1,x_2\dots x_n\) 求值,可以分治先算出 \(P_L(x)=\prod_{i=1}^{mid}(x-x_i)\)\(P_R(x)=\prod_{i=mid+1}^{n}(x-x_i)\)

由于 \(\forall i\in[1,mid],P_L(x_i)=0\),所以 \(\forall i\in[1,mid],A(x_i) = (A \bmod P_L)(x_i)\),同理 \(\forall i\in[mid+1,n],A(x_i)=(A\bmod P_R)(x_i)\)

于是分治即可,时间复杂度 \(O(n\log^2 n)\)

一个小应用:求范德蒙行列式 \(\prod_{1\leq j < i \leq n}(x_i-x_j)\)

\(F_i(x)=\prod_{j=1}^{i-1}(x-x_j)\),则答案为 \(\prod F_i(x_i)\)。可以发现多点求值在递归时可以顺便算出 \(F_i(x)\)


有一个新做法:

attention:以下的记法并不严谨,仅作为个人学习的辅助记法。

转置原理能吃吗,能吃我就去学(

一般的卷积定义为 \(f_{i+j}=\sum g_ih_j\),用形式幂级数记为 \(F(x) = G(x)\cdot H(x)\)

我们定义另一种 “卷积“ \(f_{i-j}=\sum g_ih_j\),用形式幂级数记为 \(F(x)=G(x)\times H(x)\)(注意它其实并不交换也不结合,所以不能算真正的卷积)。

那么有 \(F(a) = [x^0](F(x)\times\frac{1}{1-ax})\),将求值问题转化成了 “卷积” 问题。

注意到 \(F(x)\times(G(x)\cdot H(x)) = (F(x)\times G(x))\times H(x)\)(根据定义,这是显然的)。

一样考虑分治,尝试根据 \(F(x)\times(\prod_{i=l}^{r}\frac{1}{1-a_ix})\) 求出 \(F(x)\times(\prod_{i=l}^{mid}\frac{1}{1-a_ix})\)\(F(x)\times(\prod_{i=mid+1}^{r}\frac{1}{1-a_ix})\),根据上面那条性质算即可。

由于我们只需要求 \(x^0\) 的系数,所以分治时可以只保留 \(F(x)\times(\prod_{i=l}^r\frac{1}{1 - a_ix})\) 中有用的项(具体来说就是前 \(r-l+1\) 项),因此时间复杂度 \(O(n\log ^2 n)\)

然而这个方法只需要一次求逆得到 \(\prod_{i=1}^{n}\frac{1}{1-a_ix}\)

相关应用还没看,下次吧。


快速插值

从拉格朗日插值入手优化:\(F(x)=\sum_{i=1}^{n} y_i\times\frac{\prod_{j=1,j\not=i}^{n}(x-x_j)}{\prod_{j=1,j\not=i}^{m}(x_i-x_j)}\)

首先考虑求出 \(k_i=\prod_{j=1,j\not=i}^{n}(x_i-x_j) = \lim_{x\to x_i}\frac{\prod_{j=1}^{n}(x_i-x_j)}{x-x_i}\)。记 \(G(x)=\prod_{j=1}^{n}(x-x_j)\),洛必达一下得 \(k_i=G'(x_i)\),多点求值即可。

考虑 \(F(x)=\sum_{i=1}^{n}\frac{y_i}{v_i}\prod_{j=1,j\not = i}^{n}(x-x_j)\),可以考虑类 cdq 分治的方法求,即 \(F(x)=F_L(x)P_R(x)+F_R(x)P_L(x)\)(这里的 \(P\) 和上面的多点求值是同一定义)。


多项式复合

目前最优复杂度可以做 \(O((n\log n)^{1.5})\),然而我不会,所以咕掉了。

复合即是给定 \(F(x)=\sum f_i x^i, G(x)=\sum g_i x^i\),求 \(\sum f_i G^i(x)\)

有一个比较好的替代复杂度为 \(O(n^2+n\sqrt{n}\log n)\)

类似 BSGS,我们处理出 \(G^{i\times\sqrt{n}}(x)\)\(G^i(x)\) 的 dft,然后 \(O(n^2)\) 暴力乘并卷回去。

复合逆也可以结合拉格朗日反演公式 + 分块做到 \(O(n^2 + n\sqrt{n}\log n)\)

求复合 \(H = F\circ G\) 也可以考虑借助复合逆得到方程 \(F^{-1}\circ H = G\),在复合逆更简洁(比如 \(F\) 是树的 EGF)时效果更好。

求复合逆显然你也可以牛顿迭代,不说了。


常系数齐次线性递推

真拗口。

用于解决 \(A(x) = \frac{P(x)}{Q(x)}\) 在远处 \(x^n\) 的系数值,这里 \(\deg P = \deg Q - 1\)

传统做法是求 \(x^n\bmod \hat Q(x)\) 的系数,其中 \(\hat Q\) 表示 \(Q\) 系数的翻转(或者说这个递推的特征多项式)。

证明方法一般是用的 Cayley - Hamilton 定理,不过总有点杀鸡用牛刀的感觉。

洛谷上有老哥用了其他方法解释(没咋看懂形式化的证明),不知道能不能直接从生成函数的角度推导。

Cayley - Hamilton 定理的证明可以参考 https://blog.csdn.net/qq_35649707/article/details/104789846

考虑证 \(p(A) = O\),实际上就是证 \(A\) 作用在任何向量上都是 \(\vec{0}\)

这在 \(A\) 可对角化时是显然的,不可对角化时归纳证,即博客里的法三。

这里有一个新做法:https://www.luogu.com.cn/blog/EntropyIncreaser/solution-p4723 。由于没有实现过,并不清楚实际写起来怎么样。

update:草,上面那个新做法既好写(只需要多项式乘法)又跑得快(不加 EI 文中任何常数优化的情况下能够只跑 2s+ 的总时间)。

posted @ 2020-08-01 16:42  Tiw_Air_OAO  阅读(497)  评论(0编辑  收藏  举报