不包含MTT的板子, 这种有的话就弃疗了
/* 求逆迭代 B = 2B - AB^2 系数反转 F(1 / x) * x ^ n 除法迭代 已知 F(x) = Q(x) * G(x) + R(x) F(x),G(x) 求Q(x) R(x) F(x) = Q(x) * G(x) + R(x) mod x ^ {n + 1} F(1 / x) = Q(1 / x) * G(1 / x) + R(1 / x) mod x ^ {n + 1} Frev(x) = Qrev(x) * Grev(x) + Rrev(x) x ^(n - du_R) mod x ^ n + 1 deg_Q = n + m Deg_R < m 则 (n - dU_R > n - m) F(x) = Q(x) * G(x) + mod x ^ {n - m + 1} 然后求逆算出Q, 余数减去即可 多项式求导和积分 非常简单 多项式求ln 基本求导法则 G(x) = Ln(F(x)) G(x)‘ = Ln(F(x))‘ F(x)‘ = F(x)‘ / F(x) 没了 多项式exp F(x) = e ^ (A(x)) ln(F(x)) - A(x) = 0 折G(x) = (ln(F(x)) - A(x)) 则 F(x) = F0(x) - (G(F0(x)) / G‘(F0_(x)) = F0(x) - (Ln(F0(x)) - A(x)) * F0(x) = F0(x) (1 - ln(F0(x)) + A(x)) */ #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<queue> #include<cmath> #define ll long long #define mmp make_pair using namespace std; int read() { int nm = 0, f = 1; char c = getchar(); for(; !isdigit(c); c = getchar()) if(c == ‘-‘) f = -1; for(; isdigit(c); c = getchar()) nm = nm * 10 + c - ‘0‘; return nm * f; } const int M = (1 << 20) + 5; const int mod = 998244353; int add(int a, int b) { a += b; a -= a >= mod ? mod : 0; a += a < 0 ? mod : 0; return a; } int mul(int a, int b) { return 1ll * a * b % mod; } int poww(int a, int b) { int ans = 1, tmp = a; for(; b; b >>= 1, tmp = mul(tmp, tmp)) if(b & 1) ans = mul(ans, tmp); return ans; } namespace Poly { const int g = 3; int n; int pw[M], rw[M]; void getw() { for(int i = 1; i <= M; i <<= 1) { pw[i] = poww(g, (mod - 1) / 2 / i); rw[i] = poww(pw[i], mod - 2); } } void init(int m) { n = m; while(n > (n & -n)) n += (n & -n); } void fft(int *x, int dft) { for(int i = 0, j = 0; i < n; i++) { if(i < j) swap(x[i], x[j]); for(int l = n >> 1; (j ^= l) < l; l >>= 1); } for(int step = 1; step < n; step <<= 1) { int wn = (dft == 1) ? pw[step] : rw[step]; for(int i = 0; i < n; i += step << 1) { int wnk = 1; for(int j = i; j < i + step; j++) { int a = x[j], b = mul(wnk, x[j + step]); x[j] = add(a, b); x[j + step] = add(a, -b); wnk = mul(wnk, wn); } } } if(dft == -1) { int invn = poww(n, mod - 2); for(int i = 0; i < n; i++) x[i] = mul(x[i], invn); } } void pcpy(int *x, int a, int *y, int b) { for(int i = 0; i < a; i++) { x[i] = (i < b) ? y[i] : 0; } } void pmul(int *x, int a, int *y, int b, int *z) { static int tx[M + 5], ty[M + 5]; init(a + b - 1); pcpy(tx, n, x, a); pcpy(ty, n, y, b); fft(tx, 1), fft(ty, 1); for(int i = 0; i < n; i++) { tx[i] = mul(tx[i], ty[i]); } fft(tx, -1); for(int i = 0; i < a + b - 1; i++) { z[i] = tx[i]; } } void pinv(int *x, int m, int *y) { static int tx[M + 5], ty[M + 5]; if(m == 1) { y[0] = poww(x[0], mod - 2); return; } pinv(x, (m + 1) >> 1, y); init(m << 1); pcpy(tx, n, x, m); pcpy(ty, n, y, (m + 1) >> 1); fft(tx, 1), fft(ty, 1); for(int i = 0; i < n; i++) { tx[i] = 1ll * (2ll - 1ll * tx[i] * ty[i] % mod + mod) * ty[i] % mod; } fft(tx, -1); for(int i = 0; i < m; i++) { y[i] = tx[i]; } } void prev(int *x, int m, int *y) { for(int i = 0; i < m; i++) y[i] = x[m - 1 - i]; } void pdiv(int *x, int a, int *y, int b, int *z) { static int tx[M + 5], ty[M + 5], tz[M + 5]; prev(x, a, tx); prev(y, b, ty); for(int i = b; i < a - b + 1; ++i) ty[i] = 0; pinv(ty, a - b + 1, tz); pmul(tx, a - b + 1, tz, a - b + 1, ty); prev(ty, a - b + 1, z); } void pmod(int *x, int a, int *y, int b, int *z) { static int tx[M + 5]; if(a < b) { for(int i = 0; i < a; i++) { z[i] = x[i]; } return; } pdiv(x, a, y, b, tx); pmul(tx, a - b + 1, y, b, tx); for(int i = 0; i < b; i++) { z[i] = (x[i] - tx[i] + mod) % mod; } } void der(int *x, int m, int *y) { for(int i = 1; i < m; i++) y[i - 1] = 1ll * i * x[i] % mod; y[n - 1] = 0; } void inte(int *x, int m, int *y) { for(int i = 1; i < m; i++) y[i] = 1ll * x[i - 1] * poww(i, mod - 2) % mod; y[0] = 0; } void ln(int *x, int m, int *y) { static int tx[M + 5], ty[M + 5], tz[M + 5]; der(x, m, tx); pinv(x, m, ty); pmul(tx, m, ty, m, tz); inte(tz, m, y); } // F0(x) (1 - ln(F0(x)) + A(x)) void exp(int *x, int m, int *y) { static int ta[M + 5], tb[M + 5], tc[M + 5]; if(m == 1) { y[0] = 1; return; } exp(x, (m + 1) >> 1, y); pcpy(ta, m, y, (m + 1) >> 1); ln(ta, m, tb); for(int i = 0; i < m; i++) { tb[i] = add(x[i], -tb[i]); } tb[0] = add(tb[0], 1); pcpy(ta, (m + 1) >> 1, y, (m + 1) >> 1); pmul(ta, (m + 1) >> 1, tb, m, tc); pcpy(y, m, tc, m); } } int pool[M * 20], *cur = pool; struct poly { int *a, l; poly() {} poly(int x) { a = cur; cur += (l = x); } poly(int *b, int x) { a = cur, cur += (l = x); memcpy(a, b, sizeof (int) * l); } }; poly operator * (const poly &a, const poly &b) { poly c(a.l + b.l - 1); Poly::pmul(a.a, a.l, b.a, b.l, c.a); return c; } poly operator % (const poly &a, const poly &b) { poly c(b.l - 1); Poly::pmod(a.a, a.l, b.a, b.l, c.a); return c; } poly operator / (const poly &a, const poly &b) { poly c(b.l - 1); Poly::pdiv(a.a, a.l, b.a, b.l, c.a); return c; } poly ln(poly x) { poly y(x.l); Poly::ln(x.a, x.l, y.a); return y; } poly exp_(poly x) { poly y(x.l); Poly::exp(x.a, x.l, y.a); return y; } int main() { Poly::getw(); return 0; }
原文地址:https://www.cnblogs.com/luoyibujue/p/10504996.html
时间: 2024-11-08 23:04:50