多项式板子

dft

可以在dft是用 \(unsigned\ long\ long\) 存下每个数,注意到每次一个数只会变最多 \(mod^2\),故可以减少取模次数。

for (int hl = 1, l = 2, _ = 0; l <= n; hl = l, l <<= 1, ++_) {
	if(!rev) {
		for (int i = 0; i < n; i += l) {
			unsigned long long *x = pool + i, *y = x + hl;
			for (int j = 0, *w = w_pool[_]; j < hl; ++j, ++x, ++y, ++w) {
				unsigned long long t = *y % mod * (unsigned long long) *w;
				*y = *x + mod2 - t;
				*x = *x + t;
				if(_ == 17 && l < n) *x %= mod, *y %= mod;
			}
		}
	}
}

求逆

\(N\ =\ 2n\)

\[f\cdot g\ -\ 1\ =\ 0\ \bmod\ x^N \]

\[g\ =\ g_0\ -\ \frac{f\cdot g_0\ -\ 1}{f}\ \bmod\ x^N\ =\ g_0\ -\ (f\cdot g_0\ -\ 1)\ g\ \bmod\ x^N \]

注意到 \(g_0\ =\ g\ \bmod\ x^n\),故

\[g\ =\ (2\ -\ f\cdot g_0)\ g_0\ \bmod\ x^N \]

考虑优化 \(f\cdot g_0\ \bmod\ x^N\)\(f\)\(N\) 次多项式,\(g_0\)\(n\) 次多项式,所得结果为 \(3n\) 次多项式。由于 \(f\cdot g_0\ =\ 1\ \bmod\ x^n\),故,只用求出 \([x^i]f\cdot g_0\ (n\leq i<N)\) 即可。做长度为 \(N\)\(dft\) 即可,即求 \(f\cdot g_0\ \bmod\ x^N-1\)
\((2\ -\ f\cdot g_0)\ g_0\) 可以用类似的方法进行优化。

t = inv(n, a);
for (int i = 0; i < n; ++i) foo[i] = t.p[i];
dft(N, foo, 0);
for (int i = 0; i < N; ++i) bar[i] = a.p[i];
dft(N, bar, 0);
for (int i = 0; i < N; ++i) bar[i] = (long long) bar[i] * foo[i] % mod;
dft(N, bar, 1);
for (int i = 0; i < n; ++i) bar[i] = 0;
for (int i = n; i < N; ++i) bar[i] = mod - bar[i];
dft(N, bar, 0);
for (int i = 0; i < N; ++i) foo[i] = (long long) foo[i] * bar[i] % mod;
dft(N, foo, 1);
for (int i = 0; i < n; ++i) foo[i] = t.p[i];
return poly(N, foo);

除法

\[A(x)\ =\ B(x)\cdot Q(x)\ +\ R(x) \]

\(A^R(x)\) 表示 \(A\) 系数逆序的多项式。
则有 $$AR(x) = BR(x)\cdot QR(x) + RR(x)\cdot x^{n-m+1}$$
\(a(x)\ =\ A^R(x),\ b(x)\ =\ B^R(x),\ N\ =\ n-m+1\)

\[Q^R(x)\ =\ a(x)\cdot b^{-1}(x)\ \bmod\ x^N \]

令 $n\ =\ \frac{N}{2},\ b_0(x)\ =\ b{-1}(x) \bmod xn,\ b_1(x)\ =\ \frac{b{-1}(x) - b_0(x)}{xn},\ $$a_0(x)\ =\ a(x)\ \bmod\ xn, a_1(x) = \frac{a(x) - a_0(x)}{xn}$
先求逆得出 \(b^{-1}(x)\)

\[a(x)\cdot b^{-1}(x)\ =\ a_0\cdot b_0\ +\ (a_0\cdot b_1\ +\ a_1\cdot b_0)\cdot x^n\ +\ (a_1\cdot b_1)\cdot x^N\ =\ a_0\cdot b_0\ +\ (a_0\cdot b_1\ +\ a_1\cdot b_0)\cdot x^n\ \bmod\ x^N \]

\(b_0\)\(dft\) 结果在算 \(b^{-1}(x)\) 时已经计算过,故只需要算 \(a_0,\ a_1,\ b_1\)\(dft\)

b0 = b;
b0.resize(n);
b0 = inv(b0);
static int foo[maxn], bar[maxn];
memset(foo, 0, sizeof(foo[0]) * N);
for (int i = 0; i < n; ++i) foo[i] = b0.p[i];
dft(N, foo, 0); // b0
for (int i = 0; i < N; ++i) bar[i] = b.p[i];
dft(N, bar, 0);
for (int i = 0; i < N; ++i) bar[i] = (long long) bar[i] * foo[i] % mod;
dft(N, bar, 1);
for (int i = 0; i < n; ++i) bar[i] = 0;
for (int i = n; i < N; ++i) bar[i] = mod - bar[i];
dft(N, bar, 0);
for (int i = 0; i < N; ++i) bar[i] = (long long) foo[i] * bar[i] % mod;
dft(N, bar, 1);
for (int i = 0; i < n; ++i) bar[i] = bar[i + n], bar[i + n] = 0;
dft(N, bar, 0); // b1
static int Foo[maxn], Bar[maxn];
memset(Foo + n, 0, sizeof(Foo[0]) * n);
memset(Bar + n, 0, sizeof(Bar[0]) * n);
for (int i = 0; i < n; ++i) Foo[i] = a.p[i], Bar[i] = a.p[i + n];
dft(N, Foo, 0); // a0
dft(N, Bar, 0); // a1
for (int i = 0; i < N; ++i) bar[i] = (long long) bar[i] * Foo[i] % mod;
dft(N, bar, 1);
for (int i = 0; i < N; ++i) Bar[i] = (long long) Bar[i] * foo[i] % mod;
dft(N, Bar, 1);
for (int i = 0; i < N; ++i) foo[i] = (long long) foo[i] * Foo[i] % mod;
dft(N, foo, 1);
q.resize(N);
for (int i = 0; i < n; ++i) q.p[i] = foo[i], q.p[i + n] = ((bar[i] + Bar[i]) % mod + foo[i + n]) % mod;
q.resize(A.size() - B.size() + 1);
reverse(q.p.begin(), q.p.end());
return q;

ln

\[g\ =\ lnf\ =\ \int\frac{f'}{f} \]

\(f_0\ =\ f^{-1}\ mod\ x^n,\ f_1\ =\ \frac{f\cdot f_0\ -\ 1}{x^n},\ f'_0\ =\ f'\ mod\ x^n,\ f'_1\ =\ \frac{f'\ -\ f'_0}{x^n}\)
\(g\ =\ f'\cdot(1\ -\ (f\cdot f_0\ -\ 1))\cdot f_0\)
\(\ =\ (f'_0\ +\ f'_1\cdot x^n)(1\ -\ f_1\cdot x^n)\cdot f_0\)
\(\ =\ f'_0\cdot f_0\ +\ (f'_1\ -\ f'_0\cdot f_1)\cdot f_0\ x^n\bmod x^N\)

f.resize(N);
f0 = f;
f0.resize(n = N >> 1);
f0 = inverse(f0);
for (int i = 0; i < n; ++i) F0[i] = f0.p[i];
for (int i = 0; i < N; ++i) F1[i] = f.p[i];
dft(N, F0, 0);
dft(N, F1, 0);
for (int i = 0; i < N; ++i) F1[i] = (long long) F1[i] * F0[i] % mod;
dft(N, F1, 1);
for (int i = 0; i < n; ++i) F1[i] = F1[i + n], F1[i + n] = 0;
f = derivative(f);
for (int i = 0; i < n; ++i) DF0[i] = f.p[i], DF1[i] = (i == n - 1 ? 0 : f.p[i + n]);
dft(N, DF0, 0);
dft(N, F1, 0);
for (int i = 0; i < N; ++i) F1[i] = (long long) F1[i] * DF0[i] % mod;
dft(N, F1, 1);
for (int i = 0; i < n; ++i) F1[i] = (DF1[i] - F1[i]) % mod, F1[i + n] = 0;
dft(N, F1, 0);
for (int i = 0; i < N; ++i) F1[i] = (long long) F1[i] * F0[i] % mod;
dft(N, F1, 1);
for (int i = 0; i < N; ++i) F0[i] = (long long) F0[i] * DF0[i] % mod;
dft(N, F0, 1);
for (int i = 0; i < n; ++i) F0[i + n] = (F0[i + n] + F1[i]) % mod;
f = poly(N, F0);
f = integration(f);
f.resize(ff.size());
return f;

开方

\(g\ =\ f^{\frac{1}{2}}\bmod x^N,\ h\ =\ g^{-1}\bmod x^N,\ g_0\ =\ g\bmod x^n\)
\(g\ =\ g_0\ -\ \frac{(g_0^2\ -\ f)\cdot h_0}{2}\)
计算 \(g_0^2\ -\ f\) 时只用求出 \(g_0\) 长度为 \(n\) 的dft,然后循环卷积一下,再减去 \(g_0\) 就行了。
\((g_0^2\ -\ f)\cdot h_0\) 同理。
每次求 \(g\) 时保留 \(h_0\) 长度为 \(N\)\(dft\) 结果,优化求 \(h\)
每次求 \(h\) 时需要计算 \(g\) 长度为 \(N\)\(dft\) 结果,可以在算 \(2N\) 时的 \(g_0^2\) 时用到。

g0 = sqrt1(n, f, h, lastN);
for (int i = 0; i < n; ++i) dftg0[i] = (long long) dftg0[i] * dftg0[i] % mod;
dft(n, dftg0, 1);
for (int i = 0; i < n; ++i) {
	dftg[i] = 0;
	dftg[i + n] = (dftg0[i] - f.p[i]) % mod;
}
for (int i = n; i < N; ++i) dftg[i] = (dftg[i] - f.p[i]) % mod;
dft(N, dftg, 0);
for (int i = 0; i < n; ++i) dfth[i] = h.p[i], dfth[i + n] = 0;
dft(N, dfth, 0);
for (int i = 0; i < N; ++i) {
	dftg[i] = (long long) dftg[i] * dfth[i] % mod;
	dftg[i] = (dftg[i] & 1 ? dftg[i] + mod : dftg[i]) >> 1;
}
dft(N, dftg, 1);
g = g0;
g.resize(N);
for (int i = n; i < N; ++i) g.p[i] = -dftg[i];
if(N < lastN) {
	for (int i = 0; i < N; ++i) dftg0[i] = g.p[i];
	dft(N, dftg0, 0);
	for (int i = 0; i < N; ++i) dftg[i] = (long long) dfth[i] * dftg0[i] % mod;
	dft(N, dftg, 1);
	for (int i = 0; i < n; ++i) dftg[i] = 0, dftg[i + n] = -dftg[i + n];
	dft(N, dftg, 0);
	for (int i = 0; i < N; ++i) dfth[i] = (long long) dfth[i] * dftg[i] % mod;
	dft(N, dfth, 1);
	h.resize(N);
	for (int i = n; i < N; ++i) h.p[i] = dfth[i];
}
posted @ 2018-12-09 20:22  King_George  阅读(179)  评论(0编辑  收藏  举报