多项式求逆

概述

对于多项式 f(x)。

求逆:若存在 g(x) 满足 f(x)g(x) ≡ 1 (mod xn), 则称 g(x) 为 f(x) 在模 xn 意义下的逆元, 记作 f-1(x)。

对数:可以将其对数函数看做其与麦克劳林级数的复合:

\[\ln(1 - f(x)) = - \sum_{i=1}^{+\infty} \frac{f^i(x)}{i} \\ \ln(1 + f(x)) = \sum_{i=1}^{+\infty} \frac{(-1)^{i-1}f^i(x)}{i} \]

指数:

\[e^{f(x)} = \sum_{i=0}^{+\infty} \frac{f^i(x)}{i!} \]


求逆

首先, 对于 b>a, A(x) 在模 xb 下的逆元, 同时也是 A(x) 在模 xa 下的逆元。

于是可以求出模 \(x^{2^k}\) 下的逆元, 以下介绍倍增法。

首先, A(x) ≡ c (mod x), c 是一个常数, 则 A-1(x) (mod x) 就是 c-1

然后, 假设:

\[A(x)B'(x) \equiv 1 \mod x^{n/2} \\ A(x)B(x) \equiv 1 \mod x^n \]

由于显然有 \(A(x)B(x) \equiv 1 \mod x^{n/2}\)

于是有:\(A(x)(B(x)-B'(x)) \equiv 0 \mod x^{n/2}\), 即 \(B(x)-B'(x) \equiv 0 \mod x^{n/2}\)

然后两边平方:\(B(x)^2 + B'(x)^2 - 2B(x)B'(x) \equiv 0 \mod x^n\)

模数也可以一起平方的原因, 详见 miskoo的 blog

然后乘上 A(x) 并移项:\(B(x) \equiv 2B'(x) - A(x)B'(x)^2 \mod x^n\)

这就是倍增的过程了。

时间复杂度是 \(T(n) = T(n/2) + O(n\log n) = O(n\log n)\), 注意 \(T(n/2)\) 前面没有乘以二, 所以总复杂度不是 \(O(n\log^2 n)\)


实际代码实现的时候, 其实模数的次幂可以是任意正整数(证明同 miskoo 的证明), 只需要求出模 \(x^{\lceil n/2\rceil}\) 下的逆, 就可以用上述方法求出模 \(x^n\) 下的逆。

// 交板子过了, 保证正确
void poly_inv(int deg, int *a, int *b) {
	if(deg == 1) { b[0] = ksm(a[0], mo-2); return; }
	poly_inv((deg + 1) >> 1, a, b);
	int len = 1; while(len < (deg << 1)) len = len << 1;
	for(int i=0; i<deg; ++i) c[i] = a[i];
	for(int i=deg; i<len; ++i) c[i] = 0;
	
	for(int i=1; i<len; ++i) rv[i] = (rv[i>>1]>>1) | (i&1?len>>1:0);
	NTT(c, len, 1), NTT(b, len, 1);
	for(int i=0; i<len; ++i) b[i] = (LL)b[i] * (2ll - (LL)c[i] * b[i] % mo) % mo;
	NTT(b, len, -1);
	
	for(int i=deg; i<len; ++i) b[i] = 0;
}
posted @ 2021-01-25 10:31  xwmwr  阅读(235)  评论(0编辑  收藏  举报