多项式理论
简单记录一下
定义
中学的时候就学过吧
\(F(x) = \sum_{i} f_i x^i\)
运算
四则运算
\(F(x) + G(x) = \sum_{i} (f_i + g_i) x^i\)
\(F(x) - G(x) = \sum_{i} (f_i - g_i) x^i\)
\(F(x) \times G(x) = \sum_{i} x^i \sum_{k} f_kg_{i-k}\)
\(F(x) \times F^{-1}(x) = 1\)
\(F(x) \setminus G(x) = F(x) \times G^{-1}(x)\)
求导与求积
\(F^′(x) = \sum_{i} f_{i}ix^{i-1}\)
\(\int F(x) = C + \sum_{i} f_ix^{i + 1}\frac{1}{i+1}\)
exp与ln
根据麦克劳林级数定义
\(\exp{F(x)} = \sum_{i=0} \frac{F^i(x)}{i!}\)
\(\ln{F(x)} = -\sum_{i=1} \frac{(1 - F(x))^i}{i}\)
反转
\(F^T(x) = x^{n}F(-x)\)
\(O(n \sqrt{n})\) 多项式乘法
考虑分治
\(F = A + 2^n B\)
\(G = C + 2^n D\)
\(F \times G = AC + (AD + BC)2^n + BD2^{2n}\)
如何求解 \(AC, AD + BC, BD\)
暴力的是四次递归, 但是我们考虑 \(AD + BC + AC + BD = (A + B) \times (C + D)\)
所以三次递归 \(BC + AD\) 通过作差求得
这是一种很重要的思想
FFT
如何快速求 \(C(x) = A(x) \times B(x)\)
核心思想:n个点可以确定一个n-1次多项式
单位根
定义
复平面上单位圆分成 \(n\) 份
性质
-
\(\forall p \in \mathbb{Z}, \omega_{n}^{k} = \omega_{np}^{kp}\)
-
\(\omega_{n}^{k + \frac{n}{2}} = -\omega_{n}^{k}\)
-
\(\omega_{n}^p + \omega_{n}^{q} = \omega_{n}^{p + q}\)
根据上述的性质可以得到 单位根反演
\(\frac{\sum_{i=0}^{k-1}F(\omega_{k}^{i})}{k} = \sum[i \mid k]f_i\)
DFT
\(F(x) = FL(x^2) + xFR(x^2)\)
\( \begin{array}{l} F\left(\omega_{n}^{k}\right)=F l\left(\omega_{n / 2}^{k}\right)+\omega_{n}^{k} F R\left(\omega_{n / 2}^{k}\right) \\ F\left(\omega_{n}^{k+n / 2}\right)=F L\left(\omega_{n / 2}^{k}\right)-\omega_{n}^{k} F R\left(\omega_{n / 2}^{k}\right) \end{array} \)
递归实现
IDFT
根据单位根反演
\(c_0 = \sum[i \mid n]c_i = \frac{\sum_{i=0}^{n-1}F(\omega_{n}^{i})}{n}\)
\(c_i\) 怎么求 对这个 \(x^{n-i} F(x)\) 做
有 \(c_i = \frac{\sum_{i=0}^{n-1}\omega_{n}^{n-i}F(\omega_{n}^{i})}{n}\)
\(F(\omega_{n}^i)\) 我们已经求出来了, 所以可以直接以这个为系数, 那么求和式子就是多项式, 所以再做一遍 \(FFT\)
NTT
在 \(mod\) 意义下把 \(\omega\) 换成 \(g\) 原根
容易发现 \(\omega\) 的性质 \(g\) 在 模意义下也是成立的
常数优化
- 非递归实现
蝴蝶变换
- 求解 \(A = BC + DE\)
直接对 \(B, C, D, E\) 做 \(DFT\) 然后线性运算, 最后 \(IDFT\)
- 小范围暴力
由于 \(FFT\) 的常数较大,在数据范围较小的时候甚至不如\(O(n^2)\)的暴力卷积的优秀,如果当前的序列长度较小,可以采用暴力算法。
分治FFT
考虑类似的一类式子:
\(f_n = \sum_{i=0}^{n-1}f_i g_{n-i}\)
自己卷自己, 已知 \(g\) 求 \(f\)
我们考虑 \(cdq\)
左边对右边的贡献就是 \(\Delta x = \sum_{i=l}^{mid - 1} f_{i}g_{x-i}\)
这是一个卷积的形式平移一下 \(f\) 然后做 \(cdq\) 的时候进行 \(NTT\) 计算贡献
复杂度 \(O(nlog^2_n)\)
部分代码实现
void cdq(int l, int r, poly &f, poly &g) { //l ~ r-1
if(l == r - 1) return;
int mid = (l + r) >> 1;
cdq(l, mid, f, g);
Init_For_The_Poly_Mul((r - l));
static poly a, b;
a.set_deg(lim), b.set_deg(lim);
for(int i = l; i < mid; i ++ ) a[i - l] = f[i];
for(int i = mid - l; i < lim; i ++ ) a[i] = 0;
for(int i = 0; i < r - l; i ++ ) b[i] = g[i];
a = a * b;
for(int i = mid; i < r; i ++ )
f[i] = (f[i] + a[i - l]) % mod;
exp_cdq(mid, r, f, g);
}
牛顿迭代
考虑一个多项式函数:
\(H(F_x) = A F_x + B\)
\(F, A, B\) 均为多项式
我们现在要求 \(H(F) = 0\) 的解, 也就是函数的零点, 倍增的考虑
设 \(F_n\) 表示 \(H(F_n) = AF_n + B = 0 (\mod x^n)\) 函数在模 \(x^n\) 意义下的解
考虑它的泰勒展开式:
\(H(F_n) = H(F_{\frac{n}{2}}) + \frac{H^′(F_{\frac{n}{2}})}{1!}(F_n - F_{\frac{n}{2}}) + \frac{H^{′′}(F_{\frac{n}{2}})}{2!}(F_n - F_{\frac{n}{2}})^2 + \dots (\mod x^n)\)
因为 \(F_n - F_{\frac{n}{2}}\) 的最低次项为\(\frac{n}{2}\) 所以平方在模 \(x^n\) 意义下等于 \(0\)
所以
令 \(H(F_n) = 0\)
\(0 = H(F_{\frac{n}{2}}) + {H^′(F_{\frac{n}{2}})}(F_n - F_{\frac{n}{2}})(\mod x^n)\)
移向得到 $$F_n = F_{\frac{n}{2}} - \frac{H(F_{\frac{n}{2}})}{H^′(F_{\frac{n}{2}})} (\mod x^n)$$
有了 \(NTT\) 和 \(牛迭\) 我们有很多东西就很好算了
\(A^{-1}\) 多项式乘法逆
设 \(AB = 1\)
递推
也就是让式子 \([n=0] = \sum_i a_ib_{n-i}\) 成立
移项得到 \(b_n = -\frac{\sum_{i=0}^{n-1}b_ia_{n-i}}{a_0}\)
倍增
设 \(AB_{n}= 1 (\mod x^n)\)
考虑 \(\frac{n}{2} \rightarrow n\)
\(AB_{\frac{n}{2}} = 1 (\mod x^{\frac{n}{2}})\)
\(AB_{n} = 1 (\mod x^{n})\)
牛迭
\(H(F) = AF - 1\)
\(H^′(F) = A\)
设 \(A_{n} = A (\mod x^n)\)
\(H(F_n) = A_nF_n - 1 = 0 (\mod x^n)\)
求零点
多项式 ln
\((\ln A)^′ = \frac{A^′}{A}\)
所以 \(\ln A = \int \frac{A^′}{A}\)
需要保证 \(a_0 = 1\)
因为只有这时候, 多项式才存在 \(\ln\)
因为当 \(a_0 \not= 1\) 时 \(\ln {a_0}\) 不是有理数, 所以不存在
多项式exp
递归
\((n + 1)g_{n + 1} = \sum_{i=0}^{n} f_{i + 1}(i + 1)g_{n-i}\)
\(g_n = \frac{1}{n} \sum_{i=0}^{n-1}g_i f_{n-i} (n-i)\)
直接递归
牛迭
暴力上牛迭
\(H(F) = \ln{F} - A\)
\(H^′(F) = \frac{1}{F}\)
分治FFT
递归的式子可以分治 \(FFT\)
\(g_n = \frac{1}{n} \sum_{i=0}^{n-1}g_i f_{n-i} (n-i)\)
保证 \(a_0 = 0\) 牛迭或者递归边界就是 \(b_0 = 1\)
如果不保证的话, 根据麦克劳林级数的定义式中, 最低次数项永远不升幂, 会产生无穷求和
多项式带余除法
\(F = Q G + R\)
\(F\) 是 \(n\) 次, \(Q\) 是 \(n - m\) 次, \(G\) 是 \(m\) 次, \(R\) 是 \(m-1\)次
我们考虑怎么把 \(R\) 去掉 \(?\)
前面我们经常利用 \((\mod x^?)\) 来消去某些项。很明显,这种操作只能消去高次的项,而留下低次的项。
所以用反转
\(x^nF = QGx^n + x^nR\)
\(F^T = Q^TG^T + R^T x^{n - m + 1}\)
\(F^T = Q^TG^T (\mod x^{n-m+1})\)
\(Q^T = G^T \times (F^T)^{-1}\)
多项式求逆就可以
\(R = F - QT\)
直接算就可以
多项式开根
暴力上牛迭
\(H(F) = F^2 - A\)
\(H^′(F) = 2F\)
边界就是二次剩余
一般题目都会保证 \(a_0 = 1\)
多项式快速幂
exp + ln
\(A^k = \exp ({\ln A^k}) = \exp (k \ln{A})\)
\(O(nlogn)\)
当 \(k\) 很大的时候有:
\(A^k \equiv A^{k \mod p} (\mod p)\)
证明可以通过泰勒展开证明
要求 \(A[0] = 1\)
递推
设原多项式 \(F(x)\) 的次数为 \(k\) ,欲求 \(F(x)^p\) 的前 \(n\) 项。
对 \(F(x)^{p+1}\) 求导,能得到 \((F(x)^{p+1})'=(p+1)F(x)^pF'(x)\)
将 \(F(x)^{p+1}\) 视作 \(F(x)^p*F(x)\) 来求导,可求得 \((F(x)^{p+1})'=(F(x)^p)'F(x)+F(x)^pF'(x)\)
拿这两个式子搞搞能得到 \(p*F(x)^pF'(x)=(F(x)^p)'F(x)\)
提取系数可得:
把 \(i\) 的意义稍作修改,并整理。
前面的和式枚举复杂度都是\(O(k)\)的,一步步递推的复杂度就是\(O(nk)\)的.
要求 \(F[0] \not= 0\)
A[0] \(\not=\) 1
\(A = B \times cx^p\)
\(p\) 为最低次幂, \(c\) 为最低次幂系数
人话就是除掉 \(A[0]\) 更准确一点是除掉第一个非 \(0\) 系数次幂
\(A^k = (B + cx^p)^k = B^k + c^kx^{pk}\)
\(B\) 套用上边的做法
常系数齐次快速递推
序列 \(a\) 满足
求 \(a_n\)
\(n \le 10^9, k \le 32000\)
手摸几次发现
\(\lambda(x) = x^k - \sum_i x^{k-i}f_i\)
\(g \equiv x^n (\mod \lambda(x))\)
\(Ans = \sum_i g_i a_i\)