多项式全家桶学习笔记

Warriors_Cat

2020-08-24 09:42:27

Personal

# 多项式全家桶 ## -1.说明 这个东西是给自己看的,建议不要当做多项式参考资料,大家能看得懂就看吧qaq to do list: too many…… ## 0.参考资料 [初学 FFT 专用](https://www.luogu.com.cn/blog/command-block/fft-xue-xi-bi-ji) [NTT 和全家桶](https://www.luogu.com.cn/blog/command-block/ntt-yu-duo-xiang-shi-quan-jia-tong) ## 1. 前置模板 NTT 模板加上一堆东西。 ```cpp #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <vector> #include <queue> #include <map> #include <set> using namespace std; #define ll long long #define ull unsigned long long #define fi first #define se second #define dingyi int mid = l + r >> 1, ls = p << 1, rs = p << 1 | 1 #define y0 y_csyakioi_0 #define y1 y_csyakioi_1 #define rep(i, x, y) for(int i = x; i <= y; ++i) #define per(i, x, y) for(int i = x; i >= y; --i) #define repg(i, u) for(int i = head[u]; i; i = e[i].nxt) inline int read(){ int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ x = x * 10 + (ch ^ 48); ch = getchar(); } return x * f; } const int N = 600010, mod = 998244353, g_ = 3, invg = 332748118, I = 86583718, inv2 = 449122177, inv2I = 954952494; int n, A[N], B[N], C[N], D[N], a[N], b[N], c[N], d[N], e[N], f[N], g[N], h[N], r[N], rev, inv[N]; bool isinv; inline int fpow(int x, int p){ int ans = 1; for(; p; p >>= 1, x = 1ll * x * x % mod) if(p & 1) ans = 1ll * ans * x % mod; return ans; } inline void clr(int *A, int x){ memset(A, 0, sizeof(int)*x); } inline void cpy(int *A, int *B, int x){ memcpy(A, B, sizeof(int)*x); } inline void NTT(int typ, int *a, int lim){ if(rev != lim){ rev = lim; rep(i, 0, lim - 1) r[i] = (r[i >> 1] >> 1) | ((i & 1) ? (lim >> 1) : 0); } rep(i, 0, lim - 1) if(i < r[i]) swap(a[i], a[r[i]]); for(int mid = 1; mid < lim; mid <<= 1){ int R = mid << 1, rt = fpow(typ == 1 ? g_ : invg, (mod - 1) / R); for(int j = 0; j < lim; j += R){ int w = 1; for(int k = 0; k < mid; ++k, w = 1ll * w * rt % mod){ int x = a[j | k], y = 1ll * w * a[j | k | mid] % mod; a[j | k] = (x + y) % mod; a[j | k | mid] = (x - y + mod) % mod; } } } if(typ < 0){ int k = fpow(lim, mod - 2); rep(i, 0, lim - 1) a[i] = 1ll * a[i] * k % mod; } } inline void ptm(int *A, int *B, int len){ rep(i, 0, len - 1) A[i] = 1ll * A[i] * B[i] % mod; } inline void print(int *A, int len){ rep(i, 0, len - 1) printf("%d ", A[i]); puts(""); } inline void Polymul(int *A, int *B, int len, int m){ int lim = 1; while(lim < len) lim <<= 1; cpy(e, B, lim); clr(e + m, lim - m); NTT(1, A, lim); NTT(1, e, lim); ptm(A, e, lim); NTT(-1, A, lim); clr(A + m, lim - m); } inline void mian(){ } int main(){ int qwq = 1; while(qwq--) mian(); return 0; } ``` ## 2. 多项式求逆 [模板题](https://www.luogu.com.cn/problem/P4238) 递归思想。 记 $$R(x) F(x)\equiv1(\!\!\!\!\!\!\mod\ x^n)$$ 若有一个多项式 $R^{-1}(x)$,使得 $$R^{-1}(x)F(x)\equiv1(\!\!\!\!\!\!\mod\ x^{\frac{n}{2}})$$ 显然有 $$R(x)-R^{-1}(x)\equiv0(\!\!\!\!\!\!\mod\ x^{\frac{n}{2}})$$ 平方可得: $$R(x)^2-2R(x)R^{-1}(x)+R^{-1}(x)^2\equiv0(\!\!\!\!\!\!\mod\ x^n)$$ 等式两边乘上 $F(x)$,由 $R(x)F(x)\equiv 1(\!\!\!\!\mod\ x^n)$ 可得 $$R(x)\equiv2R^{-1}(x)-R^{-1}(x)^2F(x)(\!\!\!\!\!\!\mod\ x^n)$$ 于是可以递归了。 边界条件就是 $R(x)$ 只有一项,求个逆元即可。 ```cpp inline void Polyinv(int *A, int len){ int lim = 1; while(lim < len) lim <<= 1; a[0] = fpow(A[0], mod - 2); for(int m = 2; m <= lim; m <<= 1){ rep(i, 0, (m >> 1) - 1) b[i] = (a[i] << 1) % mod; cpy(f, A, m); NTT(1, a, m << 1); ptm(a, a, m << 1); NTT(1, f, m << 1); ptm(a, f, m << 1); NTT(-1, a, m << 1); clr(a + m, m); rep(i, 0, m - 1) a[i] = (b[i] - a[i] + mod) % mod; } cpy(A, a, len); clr(a, lim << 1); clr(b, lim << 1); clr(f, lim << 1); } ``` [AC记录](https://www.luogu.com.cn/record/36451701) ## 3. 多项式求导/积分 无模板,为后面很多多项式操作做铺垫。 求导没多大学,[参考资料](https://www.luogu.com.cn/paste/k9i6ktfv),通过这个东西知道了一些皮毛。 求导定义: 记 $\Delta y=F(x+\Delta x)-F(x)$。 那么 $$F'(x) = \lim_{\Delta x\rightarrow 0}\dfrac{\Delta y}{\Delta x}$$ 比如对 $F(x)=x^3$ 求导: $$\Delta y=F(x+\Delta x)-F(x)$$ $$=x^3+3x^2\Delta x+3x\Delta x^2+\Delta x^3-x^3$$ $$=3x^2\Delta x+3x\Delta x^2+\Delta x^3$$ 那么 $$F'(x) = \lim_{\Delta x\rightarrow0}{\dfrac{\Delta y}{\Delta x}}$$ $$=\lim_{\Delta x\rightarrow0}(3x^2+3x\Delta x+\Delta x^2)$$ $$=3x^2$$ 简单结论: >1. 若 $F(x) = kx^n(n \in \operatorname N^*)$,则 $F'(x)=knx^{n-1}$。 >证明:二项式定理展开即可。 >2. $F'(x)+G'(x)=(F(x)+G(x))'$,即求导具有**线性性**。 >证明:显然 $F(x)$ 与 $G(x)$ 互不干扰,或者手玩一下即可。 >3. $kF'(x)=(kF(x))'$ >证明:同上。 积分为求导的逆运算,记为 $\int \!F(x)dx$。 结论 1 与结论 2 结合即可求导成功。 ```cpp inline void Polyder(int *A, int len){ rep(i, 1, len - 1) A[i - 1] = 1ll * A[i] * i % mod; A[len - 1] = 0; } inline void initinv(){ if(isinv) return; isinv = inv[0] = inv[1] = 1; rep(i, 2, N - 10) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod; } inline void Polyint(int *A, int len){ initinv(); per(i, len, 1) A[i] = 1ll * A[i - 1] * inv[i] % mod; A[0] = 0; } ``` ## 4.多项式牛顿迭代 若 $G(F(x))\equiv 0(\!\!\!\!\mod\ x^n)$,且 $G(F^{-1}(x))\equiv0(\!\!\!\!\mod x^\frac{n}{2})$ 那么有: $$F(x)\equiv F^{-1}(x)-\frac{G(F^{-1}(x))}{G'(F^{-1}(x))}(\!\!\!\!\!\!\mod\ x^n)$$ 证明: $$F(x)\equiv F^{-1}(x)(\!\!\!\!\!\!\mod\ x^n)$$ 将 $G(F(x))$ 在 $F^{-1}(x)$ 处进行[泰勒展开](https://baike.baidu.com/item/%E6%B3%B0%E5%8B%92%E5%85%AC%E5%BC%8F/7681487?fr=aladdin): $$G(F(x))=\sum_{i=0}\frac{G^{(i)}(F^{-1}(x))}{i!}(F(x)-F^{-1}(x))^i$$ 其中 $i\ge 2$ 那些项的次数大于等于 $n$,于是在模 $x^n$ 意义下全没了。 $$G(F(x))=G(F^{-1}(x))+G'(F^{-1}(x))(F(x)-F^{-1}(x))$$ 由 $G(F(x))=0$ 和魔怔化简就可以得到 $$F(x)\equiv F^{-1}(x)-\frac{G(F^{-1}(x))}{G'(F^{-1}(x))}(\!\!\!\!\!\!\mod\ x^n)$$ 证毕。 ## 5. 多项式开根 [模板题](https://www.luogu.com.cn/problem/P5205) 递归思想。 记 $G(B(x))=B(x)^2-A(x)$,那么 $G'(B(x))=2B(x)$ 由多项式牛顿迭代可得 $$B(x)\equiv B^{-1}(x)-\frac{G(B^{-1}(x))}{G'(B^{-1}(x))}(\!\!\!\!\!\!\mod\ x^n)$$ 由于上面两个式子可得: $$B(x)\equiv B^{-1}(x)-\frac{B^{-1}(x)^2-A(x)}{2B^{-1}(x)}(\!\!\!\!\!\!\mod\ x^n)$$ 化简可得 $$B(x)\equiv\frac{A(x)+B^{-1}(x)^2}{2B^{-1}(x)}(\!\!\!\!\!\!\mod\ x^n)$$ 加强版先咕着,以后搞。 ```cpp inline void Polysqrt(int *A, int len){ int lim = 1; while(lim < len) lim <<= 1; c[0] = 1; for(int m = 2; m <= lim; m <<= 1){ rep(i, 0, (m >> 1) - 1) d[i] = (c[i] << 1) % mod; Polyinv(d, m); NTT(1, c, m); ptm(c, c, m); NTT(-1, c, m); rep(i, 0, m - 1) c[i] = (A[i] + c[i]) % mod; Polymul(c, d, m << 1, m); } cpy(A, c, len); clr(c, lim << 1); clr(d, lim << 1); } ``` [AC记录](https://www.luogu.com.cn/record/36454587) ## 6. 多项式除法 [模板题](https://www.luogu.com.cn/problem/P4512) 由于有余数,我们就不能用求逆来计算了。 于是重新推导式子。 $$F(x)=Q(x)G(x)+R(x)$$ $$x^nF(x^{-1})=x^nQ(x^{-1})G(x^{-1})+x^nR(x^{-1})$$ 我们定义 $k$ 次多项式 $F^R(x)=x^kF(x^{-1})$ 易证 $F(x)$ 与 $F^R(x)$ 系数翻转了一下 将上面的式子用翻转式来表示: $$F^R(x)=Q^R(x)G^R(x)+x^{n-m+1}R^R(x)$$ 模一个 $x^{n-m+1}$ 可得 $$F^R(x)\equiv Q^R(x)G^R(x)(\!\!\!\!\!\!\mod\ x^{n-m+1})$$ $$Q^R(x)\equiv \frac{F^R(x)}{G^R(x)}$$ 于是 $Q^R(x)$ 求出来了,那么 $Q(x)$ 也有了。 $Q(x)$ 求出来后 $R(x)$ 也很显然了,$R(x)=F(x)-Q(x)G(x)$。 ```cpp inline void Rev(int *A, int len){ rep(i, 0, (len >> 1) - 1) swap(A[i], A[len - i - 1]); } inline void Polydiv(int *A, int *B, int n, int m){ int len = n - m + 1; Rev(B, m); cpy(c, B, len); Rev(B, m); Rev(A, n); cpy(d, A, len); Rev(A, n); Polyinv(c, len); Polymul(c, d, len << 1, len); Rev(c, len); Polymul(B, c, n << 1, n); rep(i, 0, m - 2) B[i] = (A[i] - B[i] + mod) % mod; clr(B + m - 1, n - m + 1); cpy(A, c, len); clr(A + len, n - len); } ``` [AC记录](https://www.luogu.com.cn/record/36463935) ## 7.多项式 ln 这里的 ln 是通过求导+积分得到的。 $$B(x)\equiv \ln A(x)(\!\!\!\!\!\!\mod\ x^n)$$ $$B'(x)\equiv \ln 'A(x)A'(x)(\!\!\!\!\!\!\mod\ x^{n-1})$$ $$B'(x)\equiv\frac{A'(x)}{A(x)}(\!\!\!\!\!\!\mod\ x^{n-1})$$ $$B(x)\equiv\int\frac{A'(x)}{A(x)}dx(\!\!\!\!\!\!\mod\ x^n)$$ 没了。 ```cpp inline void Polyln(int *A, int len){ cpy(c, A, len); Polyinv(c, len); Polyder(A, len); Polymul(A, c, len << 1, len); Polyint(A, len - 1); clr(c, len); } ``` [AC记录](https://www.luogu.com.cn/record/36562082) ## 8. 多项式 exp 递归 + 牛顿迭代,推式子吧。 $$B(x)\equiv e^{A(x)}(\!\!\!\!\!\!\mod\ x^n)$$ $$\ln B(x)-A(x)\equiv0(\!\!\!\!\!\!\mod\ x^n)$$ 记 $G(B(x))=\ln B(x)-A(x)$,那么 $G'(B(x))=\frac{1}{B(x)}$。 由多项式牛顿迭代可得 $$B(x)\equiv B^{-1}(x)-\frac{G(B^{-1}(x))}{G'(B^{-1}(x))}(\!\!\!\!\!\!\mod\ x^n)$$ 将上面式子带入 $$B(x)=\equiv B^{-1}(x)-\frac{\ln B^{-1}(x)-A(x)}{\frac{1}{B^{-1}(x)}}(\!\!\!\!\!\!\mod\ x^n)$$ $$B(x)\equiv B^{-1}(x)(1-\ln B^{-1}(x)+A(x))(\!\!\!\!\!\!\mod\ x^n)$$ 可以递推了。 ```cpp inline void Polyexp(int *A, int len){ int lim = 1; while(lim < len) lim <<= 1; g[0] = 1; for(int m = 2; m <= lim; m <<= 1){ cpy(h, g, m >> 1); Polyln(h, m); rep(i, 0, m - 1) h[i] = (A[i] - h[i] + mod) % mod; h[0] = (h[0] + mod) % mod; Polymul(g, h, m << 1, m); } cpy(A, g, len); clr(g, lim << 1); clr(h, lim << 1); } ``` [AC记录](https://www.luogu.com.cn/record/36643078) ## 9. 多项式快速幂 应该是一个最为简单的板子了。 核心式子: $$A^k(x)=e^{\ln A(x) \times k}$$ 没了。 ```cpp inline void Polypow(int *A, int len, int k){ Polyln(A, len); rep(i, 0, len - 1) A[i] = 1ll * A[i] * k % mod; Polyexp(A, len); } ``` [AC记录](https://www.luogu.com.cn/record/36694673) ## 10. 多项式快速幂加强版 一堆细节,烦死了( 首先,由于 $a_0\neq 1$,所以无法直接求。 于是考虑把原多项式同时除一个 $a_0$,最后再乘回来。 但有可能 $a_0 = 0$,所以我们要找到第一个 $t$ 满足 $a_t\neq0$,然后进行计算。 具体一些: $$B(x)\equiv \left[\dfrac{A(x)}{a_tx^t}\right ]^m\times {a_t}^mx^{tm}(\bmod\ x^n)$$ 然后就是细节了: 1. 一次加强后 $m$ 变为高精度数,所以原来用低精度读入会锅。 2. 很多题解直接将 $m$ 模了 $998244353$,但当普通多项式快速幂做完需要补零的时候,这个 $m$ 可能变得很小很小,导致补零不够,可实际上 $m$ 是一个极大数,所以应当全部为 $0$。 3. 这道题主要思路就是找到第一个 $a_t \neq 0$,然后计算 $[\dfrac{A(x)}{a_tx^t}]^m \times {a_t}^m\times x^{tm}$。然而在这里计算 ${a_t}^m$ 时,$m$ 要取模的不是 $998244353$ 而是 $998244352$。 然后没了。 [AC记录](https://www.luogu.com.cn/record/37409552) ## 11. 多项式三角函数 直接套用欧拉公式: $$e^{ix}=\cos x + i\sin x$$ $$e^{-ix}=\cos x - i\sin x$$ 代入 $x = A(x)$ 可得: $$\sin A(x)=\dfrac{e^{iA(x)}-e^{-iA(x)}}{2i}$$ $$\cos A(x)=\dfrac{e^{iA(x)}+e^{-iA(x)}}{2}$$ 在模意义下 $i\equiv\omega_4^1\equiv g^{\frac{p - 1}{4}}(\bmod\ p)$,当 $p=998244353$ 时 $i=86583718$。 于是这题没了。 ```cpp inline void Polysincos(int *A, int len, int opt){//0:sin cpy(C, A, len); cpy(D, A, len); rep(i, 0, len - 1) C[i] = 1ll * C[i] * I % mod; rep(i, 0, len - 1) D[i] = 1ll * D[i] * (mod - I) % mod; Polyexp(C, len); Polyexp(D, len); if(opt) rep(i, 0, len - 1) A[i] = 1ll * (C[i] + D[i]) % mod * inv2 % mod; else rep(i, 0, len - 1) A[i] = 1ll * (C[i] - D[i] + mod) % mod * inv2I % mod; clr(C, len); clr(D, len); } ``` [AC记录](https://www.luogu.com.cn/record/40221257) ## 12. 多项式反三角函数 如同多项式 $\ln$,求导再积分。 先是 $\arcsin :$ $$F(x)\equiv \arcsin A(x)(\bmod \ x^n)$$ $$F'(x)\equiv\dfrac{A'(x)}{\sqrt{1 - A(x)^2}}(\bmod\ x^{n-1})$$ $$F(x)\equiv\int\dfrac{A'(x)}{\sqrt{1-A(x)^2}}dx(\bmod \ x^n)$$ 然后是 $\arctan :$ $$F(x)\equiv \arctan A(x)(\bmod \ x^n)$$ $$F'(x)\equiv \dfrac{A'(x)}{1 + A(x)^2}(\bmod \ x^{n-1})$$ $$F(x)\equiv \int \dfrac{A'(x)}{1+A(x)^2}dx(\bmod\ x^n)$$ 没了。 ```cpp inline void Polyasin(int *A, int len){ cpy(C, A, len); Polyder(A, len); Polymul(C, C, len << 1, len); rep(i, 0, len - 1) C[i] = mod - C[i]; C[0] = (C[0] + 1) % mod; Polysqrt(C, len); Polyinv(C, len); Polymul(A, C, len << 1, len); Polyint(A, len - 1); clr(C, len); } inline void Polyatan(int *A, int len){ cpy(C, A, len); Polyder(A, len); Polymul(C, C, len << 1, len); C[0] = (C[0] + 1) % mod; Polyinv(C, len); Polymul(A, C, len << 1, len); Polyint(A, len - 1); clr(C, len); } ``` ## inf. 全 家 桶 这一版会跟着学习进度更新。 ```cpp #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <vector> #include <queue> #include <map> #include <set> using namespace std; #define ll long long #define ull unsigned long long #define fi first #define se second #define dingyi int mid = l + r >> 1, ls = p << 1, rs = p << 1 | 1 #define y0 y_csyakioi_0 #define y1 y_csyakioi_1 #define rep(i, x, y) for(int i = x; i <= y; ++i) #define per(i, x, y) for(int i = x; i >= y; --i) #define repg(i, u) for(int i = head[u]; i; i = e[i].nxt) inline int read(){ int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ x = x * 10 + (ch ^ 48); ch = getchar(); } return x * f; } const int N = 300010, mod = 998244353, g_ = 3, invg = 332748118, I = 86583718, inv2 = 449122177, inv2I = 954952494; int n, m, A[N], B[N], C[N], D[N], a[N], b[N], c[N], d[N], e[N], f[N], g[N], h[N], r[N], rev, inv[N]; bool isinv; inline int fpow(int x, int p){ int ans = 1; for(; p; p >>= 1, x = 1ll * x * x % mod) if(p & 1) ans = 1ll * ans * x % mod; return ans; } inline void clr(int *A, int x){ memset(A, 0, sizeof(int)*x); } inline void cpy(int *A, int *B, int x){ memcpy(A, B, sizeof(int)*x); } inline void NTT(int typ, int *a, int lim){ if(rev != lim){ rev = lim; rep(i, 0, lim - 1) r[i] = (r[i >> 1] >> 1) | ((i & 1) ? (lim >> 1) : 0); } rep(i, 0, lim - 1) if(i < r[i]) swap(a[i], a[r[i]]); for(int mid = 1; mid < lim; mid <<= 1){ int R = mid << 1, rt = fpow(typ == 1 ? g_ : invg, (mod - 1) / R); for(int j = 0; j < lim; j += R){ int w = 1; for(int k = 0; k < mid; ++k, w = 1ll * w * rt % mod){ int x = a[j | k], y = 1ll * w * a[j | k | mid] % mod; a[j | k] = (x + y) % mod; a[j | k | mid] = (x - y + mod) % mod; } } } if(typ < 0){ int k = fpow(lim, mod - 2); rep(i, 0, lim - 1) a[i] = 1ll * a[i] * k % mod; } } inline void ptm(int *A, int *B, int len){ rep(i, 0, len - 1) A[i] = 1ll * A[i] * B[i] % mod; } inline void print(int *A, int len){ rep(i, 0, len - 1) printf("%d ", A[i]); puts(""); } inline void Polymul(int *A, int *B, int len, int m){ int lim = 1; while(lim < len) lim <<= 1; cpy(e, B, lim); clr(e + m, lim - m); NTT(1, A, lim); NTT(1, e, lim); ptm(A, e, lim); NTT(-1, A, lim); clr(A + m, lim - m); } inline void Polyinv(int *A, int len){ int lim = 1; while(lim < len) lim <<= 1; a[0] = fpow(A[0], mod - 2); for(int m = 2; m <= lim; m <<= 1){ rep(i, 0, (m >> 1) - 1) b[i] = (a[i] << 1) % mod; cpy(f, A, m); NTT(1, a, m << 1); ptm(a, a, m << 1); NTT(1, f, m << 1); ptm(a, f, m << 1); NTT(-1, a, m << 1); clr(a + m, m); rep(i, 0, m - 1) a[i] = (b[i] - a[i] + mod) % mod; } cpy(A, a, len); clr(a, lim << 1); clr(b, lim << 1); clr(f, lim << 1); } inline void Polysqrt(int *A, int len){ int lim = 1; while(lim < len) lim <<= 1; c[0] = 1; for(int m = 2; m <= lim; m <<= 1){ rep(i, 0, (m >> 1) - 1) d[i] = (c[i] << 1) % mod; Polyinv(d, m); NTT(1, c, m); ptm(c, c, m); NTT(-1, c, m); rep(i, 0, m - 1) c[i] = (A[i] + c[i]) % mod; Polymul(c, d, m << 1, m); } cpy(A, c, len); clr(c, lim << 1); clr(d, lim << 1); } inline void Rev(int *A, int len){ rep(i, 0, (len >> 1) - 1) swap(A[i], A[len - i - 1]); } inline void Polydiv(int *A, int *B, int n, int m){ int len = n - m + 1; Rev(B, m); cpy(c, B, len); Rev(B, m); Rev(A, n); cpy(d, A, len); Rev(A, n); Polyinv(c, len); Polymul(c, d, len << 1, len); Rev(c, len); Polymul(B, c, n << 1, n); rep(i, 0, m - 2) B[i] = (A[i] - B[i] + mod) % mod; clr(B + m - 1, n - m + 1); cpy(A, c, len); clr(A + len, n - len); } inline void Polyder(int *A, int len){ rep(i, 1, len - 1) A[i - 1] = 1ll * A[i] * i % mod; A[len - 1] = 0; } inline void initinv(){ if(isinv) return; isinv = inv[0] = inv[1] = 1; rep(i, 2, N - 10) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod; } inline void Polyint(int *A, int len){ initinv(); per(i, len, 1) A[i] = 1ll * A[i - 1] * inv[i] % mod; A[0] = 0; } inline void Polyln(int *A, int len){ cpy(c, A, len); Polyinv(c, len); Polyder(A, len); Polymul(A, c, len << 1, len); Polyint(A, len - 1); clr(c, len); } inline void Polyexp(int *A, int len){ int lim = 1; while(lim < len) lim <<= 1; g[0] = 1; for(int m = 2; m <= lim; m <<= 1){ cpy(h, g, m >> 1); Polyln(h, m); rep(i, 0, m - 1) h[i] = (A[i] - h[i] + mod) % mod; h[0] = (h[0] + 1) % mod; Polymul(g, h, m << 1, m); } cpy(A, g, len); clr(g, lim << 1); clr(h, lim << 1); } inline void Polypow(int *A, int len, int k){ Polyln(A, len); rep(i, 0, len - 1) A[i] = 1ll * A[i] * k % mod; Polyexp(A, len); } inline void Polysincos(int *A, int len, int opt){//0:sin cpy(C, A, len); cpy(D, A, len); rep(i, 0, len - 1) C[i] = 1ll * C[i] * I % mod; rep(i, 0, len - 1) D[i] = 1ll * D[i] * (mod - I) % mod; Polyexp(C, len); Polyexp(D, len); if(opt) rep(i, 0, len - 1) A[i] = 1ll * (C[i] + D[i]) % mod * inv2 % mod; else rep(i, 0, len - 1) A[i] = 1ll * (C[i] - D[i] + mod) % mod * inv2I % mod; clr(C, len); clr(D, len); } inline void Polyasin(int *A, int len){ cpy(C, A, len); Polyder(A, len); Polymul(C, C, len << 1, len); rep(i, 0, len - 1) C[i] = mod - C[i]; C[0] = (C[0] + 1) % mod; Polysqrt(C, len); Polyinv(C, len); Polymul(A, C, len << 1, len); Polyint(A, len - 1); clr(C, len); } inline void Polyatan(int *A, int len){ cpy(C, A, len); Polyder(A, len); Polymul(C, C, len << 1, len); C[0] = (C[0] + 1) % mod; Polyinv(C, len); Polymul(A, C, len << 1, len); Polyint(A, len - 1); clr(C, len); } inline void mian(){ } int main(){ int qwq = 1; while(qwq--) mian(); return 0; } ``` 哦对了如果有锅请 D 死这个彩笔(