多项式运算的一些技术

昨天白天看了看多项式的一些东西,完全看不懂,于是晚上学一学多项式的基本运算。

以下用字母 (f) 表示多项式,带下标的字母表示系数 (f_i)([n]) 表示 ( ext{mod}~x^n)

加减法

[(f+g)(x)=sum _{i=0}^infty (f_i+g_i)x^i ]

直接加法是 (O(n)) 的。由上式也可以看出,点值之和是和的点值。

乘法

多项式意义下的乘法一般是线性卷积。

可以用叉乘表示,也可以简写

[fg=(f imes g)(x)=sum _ksum _isum _j[i+j=k]f_ig_jx^k ]

[(f imes g)_k=sum _{i+j=k}f_ig_j ]

这可以用计算循环卷积的 fft 或 ntt 通过倍长实现线性卷积。

除法

[frac{f}{g}=f imes g^{-1} ]

问题就变成求一个多项式的逆元。

一个多项式是否有可能有一个完全的逆元呢?即一个多项式 (f) ,是否存在 (g) 使得 ((f imes g)(x)=1)

对于次数大于 0 的多项式 (f) ,不存在有限长度的符合要求的 (g) ,因为 (f) 的最高次和 (g) 的最高次总是无法消掉的。

那么就讨论在有限的位中的逆元,因为一般我们要求的都是序列的前一些项,之后的是不需要考虑的。

问题变成了已知一个 (g) ,求 (f) 使得

[egin{aligned} fgequiv 1 &&[n] end{aligned} ]

即在 ( ext{mod}~x^n) 的意义下求这个东西。

这类在对 (x^k) 取模意义下求的问题,一般用倍增解决。倍增的方式可以统一地用牛顿迭代得到。

设我们已经求出了 ( ext{mod}~x^frac{n}{2}) 的多项式 (f_0) ,拓展到 ( ext{mod}~x^n)

设一个函数 (H(x)) ,为了方便计算,让它在对应解的位置取 0 。在这个问题中,(H(x)=frac{1}{x}-g) ,这样对于符合要求的 (f) ,有 (H(f)=frac{1}{f}-g=g-g=0)

(f) 处对 (H) 进行泰勒展开,用 (f_0) 来逼近它,可得

[H(f)=sum _{i=0}^infty frac{H^{(i)}(f_0)(f-f_0)^i}{i!} ]

这里有一个简单的结论:(f)(f_0) 的前 (frac{n}{2}) 位是相同的。这是因为

[egin{aligned} f_0gequiv 1&&[frac{n}{2}] \ fgequiv 1 && [n] \ (f-f_0)gequiv 0 &&[frac{n}{2}] end{aligned} ]

(g e 0) ,得到结论。

也就是说,((f-f_0)^2) 的最低非 0 位至少在 (x^n) ,而我们要计算的是 ( ext{mod}~x^n) 意义下的 (f) ,所以后面的项在当前是没有用的。

[egin{aligned} H(f)equiv H(f_0)+H'(f_0)(f-f_0) && [n] end{aligned} ]

由于我们要求的 (f)( ext{mod}~x^n) 的意义下,使得 (H(f)=frac{1}{f}-g=0) ,所以有

[egin{aligned} H(f_0)+H'(f_0)(f-f_0)equiv 0 && [n]\ end{aligned} ]

我们已经得到了解的一般形式。

[egin{aligned} fequiv f_0-frac{H(f_0)}{H'(f_0)} && [n] end{aligned} ]

在上面的过程中 (H) 是一个抽象的,满足 (H(f)equiv 0 mod x^n) 的函数,它可以是任何函数。

代入我们这里的 (H(x)=frac{1}{x}-g) ,并把 (g) 看作一个常量,那就有

[egin{aligned} fequiv f_0-frac{frac{1}{f_0}-g}{-f_0^{-2}}&& [n] \ fequiv 2f_0-gf_0^2 && [n] end{aligned} ]

它只涉及到递归求出 (f_0) 和长度为 (n) 的乘法,即复杂度为

[T(n)=T(frac{n}{2})+O(nlog n)=O(nlog n) ]

一个需要注意的地方:可以发现 (f) 的式子后面有 (gf_0^2) 这一项,意味着可能会出现多余的项,需要去掉。

由上述算法可以看出,多项式有模 (x^n) 意义下的逆元,等价于常数项有逆元。

乘方

快速幂+乘法方法,(O(nlog ^2n))

也可以用下面讲到的方法做到 (O(nlog n))

开根

即求 (f) 使得

[egin{aligned} f^kequiv g && [n] end{aligned} ]

运用上面的通用方法

[egin{aligned} fequiv f_0-frac{H(f_0)}{H'(f_0)} && [n] end{aligned} ]

构造函数 (H(x)=x^k-g) ,展开可得

[egin{aligned} f&equiv f_0-frac{f_0^k-g}{kf_0^{k-1}} && [n] \ f&equiv frac{k-1}{k}f_0+frac{g}{kf_0^{k-1}} && [n] end{aligned} ]

这里使用了乘法,加法和(除法)求逆,复杂度为 (O(nlog ^2 n))

可以发现,多项式有模 (x^n) 意义下的根,等价于常数项有根。

可以用下面的方法做到 (O(nlog n))

(exp & ln)

终于到了这个时刻。

实数的开根和乘方,两种指数上的运算,可以用对数和指数的方法,变成加减法。多项式也如此。

对一个多项式 (f) ,定义 (exp f) (即 (e^f) ),为泰勒展开的形式

[exp f=sum _{k=0}^infty frac{f^k}{k!} ]

定义 (ln)(exp) 的逆运算,即 (ln (exp f)=f)

一般我们是不会需要上面的无穷形式的,而是需要得到前 (n) 位,所以求解仍然在 ( ext{mod}~x^n) 意义下进行。

如何求这两个东西呢?

(ln)

[egin{aligned} fequiv ln g && [n] end{aligned} ]

对两边进行求导

[egin{aligned} f'equiv frac{g'}{g} && [n] \ fequiv int frac{g'}{g} && [n] end{aligned} ]

多项式的求导和积分都是 (O(n)) 的,其中用到的逆元是 (O(nlog n)) 的,所以复杂度为 (O(nlog n))

(exp)

(f) 使得

[egin{aligned} ln fequiv g&& [n] end{aligned} ]

运用通用方法,设 (H(x)=ln x-g) ,那么

[egin{aligned} f&=f_0-frac {H(f_0)}{H'(f_0)} && [n] \ f&=f_0-frac {ln f_0-g}{frac{1}{f_0}} && [n] \ f&=f_0(1-ln f_0+g) && [n] end{aligned} ]

后记

大概就是这样啦

主要就是牛顿迭代倍增的方法和神奇的 (ln)(exp)

最近会做一些多项式相关的题,研究一下生成函数吧。

原文地址:https://www.cnblogs.com/owenyu/p/7576568.html