省选复习 - 多项式全家桶 (咕咕咕)
多项式全家桶
听起来很吓人的名字(在我学之前),慢慢知识积累上去,你会发现它就是一堆数学推导。
不断更新中...
当前进度:多项式exp / 常系数齐次线性递推
基础知识
微积分
(暂时)并不需要太高的水平,最基本的会即可。
基础求导:
\(C'=0\)
\((x^n)'=nx^{n-1}\)
\((e^x)'=e^x\)
\(ln'(x)=\dfrac{1}{x}\)
\((Cf(x))'=Cf'(x)\)
\((f\pm g)'=f'\pm g'\)
\((fg)'=f'g+fg'\)
\((\dfrac{f}{g})'=\dfrac{f'g-fg'}{g^2}\)
\(f(g(x))'=f'(g(x))g'(x)\)
基础积分:
把上面这些反过来
FFT/NTT
这还要讲?
泰勒展开
现在已知一个函数 \(f(x)\)。要用一个多项式函数 \(g(x)\) 逼近它
考虑先选取一个起点 \(x_0\),以这个位置为参考 (一般这个位置要好算一些,或者有可以利用的数值)
然后我们的主体思路是,让 \(f,g\) 在 \(x_0\) 处的值,一阶导,二阶导,三阶导...都相同。
首先我们让 \(f,g\) 在 \(x_0\) 处相同。那 \(g\) 先加上一项 \(f(x_0)\) 的常数。
然后我们让它的一阶导相同,那我们要给它来点多项式了。但是注意我们不能改变取值,于是我们只能加上 \(x-x_0\) 的若干倍。
设 \(g_k\) 表示一个函数,它在 \(x_0\) 处的 \(k\) 阶导和 \(f\) 相同。
考虑 \(g_1\):
当 \(x=x_0\) 时,\(g_1'(x)=f'(x_0)\)
同时积分,\(g_1(x)=xf'(x_0)+C\)
为了凑 \(x-x_0\),我们令 \(g_1(x)=(x-x_0) f'(x_0)\)
考虑 \(g_2\):
同时积分两次
\(g_2(x_0)=\dfrac{1}{2} f''(x_0)x_0^2 + C(x)\),\(C(x)\) 是任意至多一次的多项式。
同理,我们令 \(g_2(x)=\dfrac{1}{2}f''(x_0) (x-x_0)^2\)
这里出现了分数,容易发现这个分数是积分的时候积出来的,积了多少次,就会有多少个,所以是一个阶乘
所以 \(g_k(x)=\dfrac{f^{(k)}(x_0) (x-x_0)^k}{k!}\)
然后把所有的 \(g_k\) 和常数项加起来,得到:
牛顿迭代
首先,我们对一个多项式 \(\mod {x^n}\),意思就是取前 \(n-1\) 项,这个东西想想就明白了。
另外,因为同余 \(\equiv\) 很不好打,后面 \(=\) 也表示同余 —— 这个写法很不好,但看到后面有 \(\pmod{...}\) 便可知这个 \(=\) 表示同余。
回到正题。现在我们要解一个多项式方程 \(E(f)=0\),其中 \(f\) 是一个未知多项式,我们要找出来它。
而实际问题中我们一般只需要 \(f\) 的前 \(k\) 项,也就是 \(\mod x^k\) 的解。
假设我们知道了 \(E(f_0)=0 \pmod{x^n}\),要找一个 \(E(f)=0 \pmod{x^{2n}}\)
假设能这么求,那么求 \(\log\) 次,就可以求出 \(\mod x^k\) 的解了。
我们在 \(f_0\) 处展开 \(E\),并求 \(f\) 位置的值 (没错,展开结果是一个多项式套多项式,会有若干个 \(f\) 的若干次方)
\(E(f)=E(f_0)+E'(f_0)(f-f_0)+\dfrac{E''(f_0)(f-f_0)^2}{2!}+...\)
我们强制令 \(f=f_0 \pmod{x^n}\),容易证明,如果 \(E\) 有解,那这样一定能找到一个解。
证:
假设 \(E(g)=0 \pmod{x^{m}}\),其中 \(m\) 是一个足够大的数 —— 比我们要用的所有 \(n\) 大
考虑 \(f=g\mod x^n\)
在 \(g\) 处展开 \(E\),代入 \(f\) 求值
\(E(f)=E(g)+E'(g)(f-g)+...\)
由于 \(f=g \pmod{x^n}\),所以 \(f-g=0 \pmod{x^n}\) ,于是 \(E(f)=E(g)=0 \pmod{x^n}\)
也就是我们要找的 \(\mod x^n\) 的解,当然,\(m\) 再大一点,容易证明,把 \(n\) 换成 \(2n\) ,或者是我们想要的 \(k\) ,都是成立的,都能找到解
然后注意到 \((f-f_0)^2=0\pmod{x^{2n}}\),后面的次数更大,都包含这个因子 —— 所以从 \(2\) 开始我们全都不用要了。
然后 \(E(f)=E(f_0)+E'(f_0)(f-f_0)\)
移项并整理:
然后每次这么求一遍就可以了。关于如何算除法,后面再说。
牛顿迭代的代码实现
假设我们现在已经知道了多项式乘法,这里直接假设封装了 operator (实际上我并没有这么干,因为我试过一次,很慢,也不知如何优化)
相当于半个伪代码和C++
void solve(euqation E,poly& g,int n)
// E 是那个方程
// 实际代码实现中, 通常是传一个方程的参数进来, 然后通过推式子手动求方程的值和求导之类的
// 另外, 一般这里的g是传数组进来, 就不用&了
{
int len,lim;
poly g=trival(); // 先瞪出来一个trival的边界值
for(len=1;len<=(n<<1);len<<=1)
{
lim=len<<1; // 这个是 FFT/NTT 要用的
E_=deri(E); // 求导
// 实际上我们是需要手动求导的, 而且不会写成这样, 这里仅供示意
g=g-E(g)*inv(E_(g)); // inv: 求逆, 后面讲, 乘以一个多项式的逆相当于除
// 顺便, 一般这里求 E 啥的还要再来一堆辅助数组
}
return g;
}
别问我为啥要贴这个,我初学的时候尝试自己想怎么写,但是一直不知道lim和len咋搞
如果您自己想出来了,恭喜你,把我吊打了
多项式正题
多项式乘法
FFT/NTT 直接上
多项式求逆
已知 \(f\),求 \(g\) 使 \(fg=1 \pmod{x^k}\)
记 \(g=f^{-1}\)。由于逆元的对称性,\(f=g^{-1}\)
牛顿迭代需要用除法,而多项式求逆就是用来解决除法的,所以牛顿迭代比多项式求逆高 —— 换句话说我们没法用牛顿迭代算多项式求逆。这就好比你没法生下来你妈,因为你是你妈生的 超 级 加 辈
但是这个思路值得借鉴。假设有\(g_0\) 使 \(fg_0=1 \pmod{x^n}\),求 \(g\) 使 \(fg=1 \pmod{x^{2n}}\)。还是令前 \(n\) 项相同,然后考虑 \((g-g_0)^2\),显然它 \(=0 \pmod{x^{2n}}\)。
展开它,变成
\(g^2-2gg_0+g_0^2=0\pmod{x^{2n}}\)
同时乘以 \(f\)
\(fg^2-2fgg_0+fg_0^2=0\pmod{x^{2n}}\)
我们设 \(fg=1 \pmod{x^{2n}}\),所以可以代入一下变成
\(g-2g_0+fg_0^2=0\pmod{x^{2n}}\)
移项得:
然后迭代即可。上面提到,除相当于乘以逆元。于是就可以算除法了。
多项式对数函数(ln)
要求 \(g(x)=\ln(f(x)) \pmod{x^k}\)
以 \(x\) 为主元来导,\(g'(x)=\dfrac{1}{f(x)}f'(x)\)
然后积回去:
(为啥打中间是因为这样的积分好看,打在行间就是 \(\int\))
多项式指数函数(exp)
非常好听的名字:exp。它也有很完美的性质,一切都是 \(e\) 这个神秘数字的魅力。
先回到正题。要求:\(g=\exp(f)=e^f \pmod{x^n}\)
相当于 \(\ln(g)-f=0\)
设 \(E(g)=\ln(g)-f\)。易得 \(E'(g)=\dfrac{1}{g}\)(这里设 \(g\) 为主元,然后 \(f\) 就是常数,也不用链式法则了)
换句话说求的是 \(\dfrac{dE(g)}{dg}\)
\(g=g_0-\dfrac{E(g_0)}{E'(g_0)}=g_0-\dfrac{\ln(g_0)-f}{\dfrac{1}{g_0}}\)
整理一下就是
然后它的完美性质是甚么?
假设我们知道一个东西 \(A\) ,它的数量的的生成函数是 \(F\)
然后有另一个东西 \(B\),它的数量的生成函数是 \(G\)
然后 \(B\) 是由若干个 \(A\) 无序拼起来的。
这样的例子很多,比如说置换是由循环置换拼起来的,任意图是由若干连通图拼起来的,森林是由树拼起来的...
然后 \(G=\exp(F)\)
为什么呢?枚举 \(A\) 用了多少个,假设是 \(i\) 个。然后它们的大小的和要等于 \(n\),也就是一个多元卷积的形式。又因为是无序的,所以要除以 \(i!\)
于是有 \(G=\sum\limits_{i=1}^{\infin}\dfrac{F^i}{i!}\)
然后这玩意就是 \(\exp(x)\) 在 \(x_0=0\) 处的展开 (容易验证)。于是 \(G=\exp(F)\)
当然它还有更多完美的性质,此处略
不太有用的东西
指多项式开根/三角函数
题目里没见到过,只有板子里有。 也可能是我too young too simple
反正牛迭随便推一下就行了
多项式快速幂
先开 \(\ln\),然后乘以 \(k\) (我们要的幂),然后再 \(e\) 回来。一个 \(\log\),比倍增快速幂快。
多项式带余除法
给定 \(F,G\),次数分别是 \(n,m\)。
求 \(Q,R\) 使得 \(F=QG+R\),其中 \(R\) 的次数必须小于 \(m\) —— 容易证明存在唯一的 \(G,R\)。
(其中我们称 \(Q\) 为商,\(R\) 为余数)
考虑模 \(x^n\) 这个操作,它可以去掉多项式从 \(n\) 开始的更高的次数,只保留 \([0,n-1]\) 次。换句话说,它体现在数组上去掉了一个 后缀。
然后现在比较不好处理的就是这个 \(R\) 。我们希望用一个类似取模的东西,去掉一个 前缀,直接多项式乘法逆就可以求出 \(Q\) 了。
那这不是很好办么,前缀反过来就是后缀了。但是请注意,\(R\) 的次数很小,反过来的时候注意补项。
于是得到了问题的解决办法:
- \(F,G\) 做一遍 \(reverse\),设得到了 \(F_r,G_r\)。然后 \(Q=F_r\times (G_r)^{-1}\)
- \(R=F-QG\),直接乘然后减就完了
常系数齐次线性递推
单独出来写吧,有点长
见 ko↑ko↓
多项式多点求值 / 快速插值
咕咕咕~
多项式复合 / 多项式复合逆
咕咕咕~
普通多项式和下降幂多项式的转化
斯特林数瞎搞一番就行了
(本质上也是咕咕咕)
鸽 王 争 霸 赛