多项式全家桶

多项式乘法

\(FFT \Rightarrow\) 传送门

\(NTT \Rightarrow\) 传送门

\(FFT\)

void FFT(int lim, Complex *a, int op) {
	for (int i = 0; i < lim; ++i)
		if (i < r[i]) swap(a[i], a[r[i]]);
	for (int len = 2; len <= lim; len <<= 1) {
		int mid = len >> 1;
		Complex Wn = {cos(Pi / mid), op * sin(Pi / mid)};
		for (int i = 0; i < lim; i += len) {
			Complex w = {1, 0};
			for (int j = 0; j < mid; ++j, w = w * Wn) {
				Complex x = a[i + j], y = w * a[i + j + mid];
				a[i + j] = x + y;
				a[i + j + mid] = x - y;
			}
		}
	}
}

\(NTT\)

ll root(const ll p) {
	for (int i = 2; i <= p; ++i) {
		int x = p - 1;
		bool flag = true;
		for (int k = 2; k * k <= p - 1; ++k) if (!(x % k)) {
			if (ksm(i, (p - 1) / k) == 1) {
				flag = false;
				break;
			}
			while (!(x % k)) x /= k;
		}
		if (flag && (x == 1 || ksm(i, (p - 1) / x) != 1)) return i;
	}
}
void NTT(int lim, ll *a, int op) {
	for (int i = 0; i < lim; ++i)
		if (i < r[i]) swap(a[i], a[r[i]]);
	for (int len = 2; len <= lim; len <<= 1) {
		int mid = len >> 1;
		ll Wn = ksm(op == 1 ? G : Gx, (mod - 1) / len);
		for (int i = 0; i < lim; i += len) {
			ll w = 1;
			for (int j = 0; j < mid; ++j, w = (w * Wn) % mod) {
				ll x = a[i + j], y = w * a[i + j + mid] % mod;
				a[i + j] = (x + y) % mod;
				a[i + j + mid] = (x - y + mod) % mod;
			}
		}
	}
}

多项式求逆

当多项式只有一项时,那么显然 \(G_0\) 就是 \(F_0\) 的逆元。

考虑一般情况下,如果我们已知 \(F(x) H(x) \equiv 1 (\mod x^{\lceil \frac{n}{2} \rceil})\) ,如何求出 \(F(X)G(x) \equiv 1(\mod x^n)\)

已知 \(F(x) H(x) \equiv 1 (\mod x^{\lceil \frac{n}{2} \rceil})\)

又显然 \(F(X)G(x) \equiv 1(\mod x^{\lceil \frac{n}{2} \rceil})\)

\(x ^ n\) 相当于将次数大于等于 \(n\) 的项舍去了,模 \(x^{\lceil \frac{n}{2} \rceil}\) 则相当于舍去了更多的项,所以前者满足,后者一定满足。

将两个式子相减 \(F(x)\left[ G(x) - H(x) \right] \equiv 0 (\mod x ^ {\lceil \frac{n}{2} \rceil})\)

\(G(x) - H(x) \equiv 0 (\mod x ^ {\lceil \frac{n}{2} \rceil})\)

然后将两边·平方一下

\[G^2(x) - 2G(x)H(x)+ H^2(x) \equiv 0 (\mod x^{\lceil \frac{n}{2} \rceil}) \]

由于 \(G(x)-H(x)\) 在 模 \(x^{\lceil \frac{n}{2} \rceil}\) 下为 \(0\),所以这个式子的结果的 \(0\)\(\lceil \frac{n}{2} \rceil - 1\) 次项系数都为 \(0\)

而平方之后,对于结果的 \(i\) 次项(\(0 \le i \le 2 \times \lceil \frac{n}{2} \rceil - 1\)),其系数 \(a_i=\sum \limits_{j=0}^{i} a_j a_{i-j}\), 其中 \(a_j\)\(a_{i-j}\) 必定至少有一项小于等于 \(\lceil \frac{n}{2} \rceil - 1\),所以可以得知,平方之后的式子在模 \(x^n\) 意义下也为 \(0\)

\[G^2(x) - 2G(x)H(x)+ H^2(x) \equiv 0 (\mod x^{n}) \]

给式子乘上一个 \(F(x)\),得到

\[F(x)G^2(x) - 2F(x)G(x)H(x)+ F(x)H^2(x) \equiv 0 (\mod x^{n}) \]

由多项式乘法逆的定义 \(F(x)G(x)\equiv 0(\mod x ^n)\)可以得到

\[G(x) - 2H(x)+ F(x)H^2(x) \equiv 0 (\mod x^{n}) \]

再移项

\[G(x) \equiv 2H(x)+ F(x)H^2(x) (\mod x^{n}) \]

于是就可以不断倍增,求出多项式乘法逆。

void polyinv(int len, int *A, int * B) {
	if (len == 1) {
		B[0] = fpow(A[0], P - 2);
		return;
	}
	static int tmp[_];
	polyinv((len + 1) >> 1, A, B);
	int lim = 1, k = 0;
	while (lim < (len << 1)) lim <<= 1, ++k;
	for (int i = 0; i < lim; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (k - 1));
	copy(A, A + len, tmp);
	fill(tmp + len, tmp + lim, 0);
	NTT(lim, tmp, 1);
	NTT(lim, B, 1);
	for (int i = 0; i < lim; ++i)
		B[i] = (2ll - 1ll * B[i] * tmp[i] % P + P) * B[i] % P;
	NTT(lim, B, -1);
	fill(B + len, B + lim, 0);
}

多项式除法

给定一个 \(n\) 次多项式 \(F(x)\) 和一个 \(m\) 次多项式 \(G(x)\) ,求出多项式 \(Q(x)\), \(R(x)\),满足:

  • \(Q(x)\) 次数为 \(n-m\)\(R(x)\) 次数小于 \(m\)
  • \(F(x) = Q(x) * G(x) + R(x)\)

首先考虑一种操作 \(R\) ,使得

\[A^R(x) = x^n A(\frac{1}{x}) \]

这个操作实际上是将 \(A(x)\) 的系数反转。

接下来,考虑将 \(F(x) = Q(x) * G(x) + R(x)\) 中的 \(x\) 全部用 \(\frac{1}{x}\) 替代,然后等式两边同时乘上 \(x ^ n\),得到

\[x^n F(\frac{1}{x}) = x^n Q(x) * G(x) + x^n R(x) \\ x^n F(\frac{1}{x}) = x^{n-m} Q(x) * x^m G(x) + x^{n-m+1} x^{m-1} R(x) \]

\[F^R(x) = Q^R(x) G^R(x) + x^{n-m+1} R^R(x) \]

比较难搞的是 \(R(x)\),考虑怎么消掉它。

仔细观察一下,可以发现,\(Q(x)\) 反转后次数不会高于 \(n-m\),而 \(x^{n-m+1} R^R(x)\) 的最低次项次数高于 \(n-m\),因此,将上面的式子放到模 \(x^{n-m+1}\) 意义下,\(R(x)\) 就被消掉了。而由于 \(F(x),G(x)\) 是已知的元素,因此不会有任何问题。

所以

\[F^R(x) = Q^R(x) G^R(x) (\mod x^{n-m+1}) \]

\[Q^R(x) \equiv F^R(x)G^R(x)^{-1} (\mod x^{n-m+1}) \]

系数反转可以直接 \(\text{reverse}\) 实现,只要求出 \(G^R(x)\), 就可以得到 \(Q^R(x)\),然后反转回来回代,就得到了 \(R(x)\)。时间复杂度 \(O(N\log N)\)

多项式开方

已知 \(F(x)\) ,求 \(G(x)\) 使得 \(G^2\equiv F\pmod{x^n}\)

posted @ 2020-01-20 19:36  newbielyx  阅读(130)  评论(0编辑  收藏  举报