# 多项式整理

## 多项式求逆元

$$A(x)A^{-1}(x)\equiv 1\pmod {x^n}$$

### 算法

$$A(x)B(x)\equiv 1\pmod {x^{\lceil\frac n2\rceil}}$$

$$A(x)A^{-1}(x)\equiv 1\pmod {x^{\lceil\frac n2\rceil}}$$

$$A(x)(B(x)-A^{-1}(x))\equiv 0\pmod{x^{\lceil\frac n2\rceil}}$$

$$B(x)-A^{-1}(x)\equiv 0\pmod{x^{\lceil\frac n2\rceil}}$$

$$B^2(x)+A^{-2}(x)-2B(x)A^{-1}(x)\equiv 0\pmod {x^n}$$

$$B^2(x)A(x)+A^{-1}(x)-2B(x)\equiv 0\pmod {x^n}$$

$$A^{-1}(x)\equiv B(x)(2-B(x)*A(x))\pmod {x^n}$$

### 代码实现

// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#include<algorithm>
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<21, stdin), p1 == p2) ? EOF : *p1++)
#define swap(x,y) (x ^= y, y ^= x, x ^= y)
#define mul(a, b) 1ll * a * b % P
#define add(a, b) (a + b >= P ? a + b - P : a + b)
#define dec(a, b) (a - b <  0 ? a - b + P : a - b)
#define rg register
const int MAXN = (1 << 21) + 10, P = 998244353, G = 3, Gi = 332748118;
char buf[1<<21], *p1 = buf, *p2 = buf;
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
char obuf[1<<24], *O=obuf;
void print(int x) {
if(x > 9) print(x / 10);
*O++= x % 10 + '0';
}
inline int fastpow(int a, int k) {
int  base = 1;
while(k) {
if(k & 1) base = mul(a, base);
a = mul(a, a); k >>= 1;
}
return base % P;
}
int N, r[MAXN], X[MAXN], Y[MAXN], A[MAXN], B[MAXN], Og[MAXN];
inline void NTT(int  *A, int type, int len) {
int limit = 1, L = 0;
while(limit < len) limit <<= 1, L++;
for(rg int i = 0; i < limit; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (L - 1));
for(rg int i = 0; i < limit; i++) if(i < r[i]) swap(A[i], A[r[i]]);
for(rg int mid = 1; mid < limit; mid <<= 1) {
int  R = mid << 1;
int  W = fastpow(G, (P - 1) / R); Og[0] = 1;
for(rg int j = 1; j < mid; j++) Og[j] = mul(Og[j - 1], W);
for(rg int j = 0; j < limit; j += R) {
for(rg int k = 0; k < mid; k++) {
const int x = A[j + k], y = mul(Og[k], A[j + k + mid]);
A[j + k] = add(x, y), A[j + k + mid] = dec(x, y);
}
}
}
if(type == -1) {
std::reverse(&A[1], &A[limit]);
for(int i = 0, inv = fastpow(len , P - 2); i < limit; i++)
A[i] = 1ll * A[i] * inv % P;
}
}
void Inv(int *a, int *b, int len) {// a要求的多项式 b逆元 len：要求的逆元的长度
if(len == 1) {
b[0] = fastpow(a[0], P - 2);
return ;
}
Inv(a, b, len >> 1);
for(rg int i = 0; i < len; i++) A[i] = a[i], B[i] = b[i];
NTT(A, 1, len << 1); NTT(B, 1, len << 1);
for(rg int i = 0; i < (len << 1); i++) A[i] = mul(mul(A[i], B[i]), B[i]) ;
NTT(A, -1, len << 1);
for(rg int i = 0; i < len; i++) b[i] = (1ll * (b[i] << 1) % P + P - A[i] ) % P;
}
int main() {
#ifdef WIN32
freopen("a.in","r",stdin);
#endif
for(int i = 0; i < N; i++) X[i] = (read() + P) % P;
int Len; for(Len = 1; Len < N; Len <<= 1);
Inv(X, Y, Len);
for(int i = 0; i < N; i++) print(Y[i]), *O++ = ' ';
fwrite(obuf, O-obuf, 1 , stdout);
return 0;
}

## 多项式除法

$$A(x) = D(x)B(x) + R(x)$$

### 算法

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

$$A(x)=B(x)D(x)+R(x)$$

$$\begin{eqnarray*} x^n A(\frac{1}{x}) &=& x^{n - m}D(\frac{1}{x}) x^mB(\frac{1}{x}) + x^{n - m + 1}x^{m - 1}R(\frac{1}{x}) \\ A^R(x) &=& D^R(x)B^R(x) + x^{n - m + 1}R^R(x) \end{eqnarray*}$$

$$A^R(x)\equiv B^R(x)D^R(x)\pmod{x^{n-m+1}}$$

$$A^R(x) * B^{-R}(x)\equiv D^R(x)\pmod{x^{n-m+1}}$$

## 多项式取模

实际就是上面的$R(x)$

### 代码实现

// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#include<algorithm>
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<21, stdin), p1 == p2) ? EOF : *p1++)
#define swap(x,y) (x ^= y, y ^= x, x ^= y)
#define mul(a, b) 1ll * a * b % P
#define add(a, b) (a + b >= P ? a + b - P : a + b)
#define dec(a, b) (a - b <  0 ? a - b + P : a - b)
#define rg register
using namespace std;
const int MAXN = 1e6, P = 998244353, Gi = 3;
char buf[1<<21], *p1 = buf, *p2 = buf;
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
char obuf[1<<24], *O=obuf;
void print(int x) {
if(x > 9) print(x / 10);
*O++= x % 10 + '0';
}
inline int fastpow(int a, int k) {
int  base = 1;
while(k) {
if(k & 1) base = mul(a, base);
a = mul(a, a); k >>= 1;
}
return base % P;
}
int N, r[MAXN], A[MAXN], B[MAXN], Og[MAXN], F[MAXN], Q[MAXN], G[MAXN], R[MAXN], Ginv[MAXN], Atmp[MAXN], Btmp[MAXN];
int GetLen(int x) {
int len;
for(len = 1; len <= x; len <<= 1);
return len;
}
inline void NTT(int  *A, int type, int len) {
int limit = 1, L = 0;
while(limit < len) limit <<= 1, L++;
for(rg int i = 0; i < limit; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (L - 1));
for(rg int i = 0; i < limit; i++) if(i < r[i]) swap(A[i], A[r[i]]);
for(rg int mid = 1; mid < limit; mid <<= 1) {
int  R = mid << 1;
int  W = fastpow(Gi, (P - 1) / R); Og[0] = 1;
for(rg int j = 1; j < mid; j++) Og[j] = mul(Og[j - 1], W);
for(rg int j = 0; j < limit; j += R) {
for(rg int k = 0; k < mid; k++) {
const int x = A[j + k], y = mul(Og[k], A[j + k + mid]);
A[j + k] = add(x, y), A[j + k + mid] = dec(x, y);
}
}
}
if(type == -1) {
std::reverse(&A[1], &A[limit]);
for(int i = 0, inv = fastpow(len , P - 2); i < limit; i++)
A[i] = 1ll * A[i] * inv % P;
}
}
void Inv(int *a, int *b, int len) {// a要求的多项式 b逆元 len：要求的逆元的长度
if(len == 1) {
b[0] = fastpow(a[0], P - 2);
return ;
}
Inv(a, b, len >> 1);
for(rg int i = 0; i < len; i++) A[i] = a[i], B[i] = b[i];
NTT(A, 1, len << 1);
NTT(B, 1, len << 1);
for(rg int i = 0; i < (len << 1); i++) A[i] = mul(mul(A[i], B[i]), B[i]) ;
NTT(A, -1, len << 1);
for(rg int i = 0; i < len; i++) b[i] = (1ll * (b[i] << 1) % P + P - A[i] ) % P;
for(rg int i = 0; i < (len << 1); i++) A[i] = B[i] = 0;
}
void Mul(int *a, int *b, int *c, int N, int M) {
int len = GetLen(max(N, M)) << 1;
for(int i = 0; i <= N; i++) Atmp[i] = a[i];
for(int i = 0; i <= M; i++) Btmp[i] = b[i];
NTT(Atmp, 1, len); NTT(Btmp, 1, len);
for(int i = 0; i <= len; i++) c[i] = 1ll * Atmp[i] * Btmp[i] % P, Atmp[i] = Btmp[i] = 0;
NTT(c, -1, len);
}
int main() {
#ifdef WIN32
freopen("a.in","r",stdin);
#endif
for(int i = 0; i <= N; i++) F[i] = read();
for(int i = 0; i <= M; i++) G[i] = read();
reverse(F, F + N + 1); reverse(G, G + M + 1);
//for(int i = 0; i <= N - M; i++) Ginv[i] = G[i];//tag
Inv(G, Ginv, GetLen(N - M));
Mul(F, Ginv, Q, N - M, N - M);
reverse(Q, Q + N - M + 1);
for(int i = 0; i <= N - M; i++) print(Q[i]), *O++ = ' '; *O++ = '\n';
reverse(F, F + N + 1); reverse(G, G + M + 1);
Mul(Q, G, R, N - M, M);
for(int i = 0; i < M; i++)
print(dec(F[i], R[i])), *O++ = ' ';
fwrite(obuf, O-obuf, 1 , stdout);
return 0;
}

## 泰勒展开

$$g(x)=g(0)+\frac{f^{1}(0)}{1!}x+\frac{f^{2}(0)}{2!}x^{2}+……+\frac{f^{n}(0)}{n!}x^{n}$$

$f^n$表示对$f$进行$n$次求导

## 普通牛顿迭代法

$$f(x)=f(x_0)+f'(x_0)(x-x_0)+\frac {f''(x_0)(x-x_0)^2}2+\cdots$$

$$f(x)=f(x_0)+f'(x_0)(x-x0)=0$$

$$x=x0-\frac{f(x_0)}{f'(x_0)}$$

## 多项式牛顿迭代法

### 用途：

$$G(F(x)) \equiv 0 \pmod {x^n}$$

### 算法

$$G(x) \equiv 0$$

$$G(F_0(x)) \equiv 0 \pmod {x^{\lceil \frac{n}{2} \rceil}}$$

$$\begin{eqnarray*} G(F(x)) & = & G(F_0(x)) \\ & + & \frac{G'(F_0(x))}{1!}\left(F(x) - F_0(x)\right) \\ & + & \frac{G''(F_0(x))}{2!}\left(F(x) - F_0(x)\right)^2 \\ & + & \cdots \end{eqnarray*}$$

$$G(F(x)) \equiv G(F_0(x)) + G'(F_0(x))\left(F(x) - F_0(x)\right) \pmod {x^n}$$

$$F(x) \equiv F_0(x) - \frac{G(F_0(x))}{G'(F_0(x))} \pmod {x^n}$$

## 多项式开根

$B^2(x) \equiv A(x) \pmod{x^n}$

$F^2(x) - A(x) \equiv 0 \pmod{x^n}$

$$\begin{eqnarray*} F(x) & \equiv & F_0(x) - \frac{F_0^2(x) - A(x)}{2F_0(x)} \\ & \equiv & \frac{F_0^2(x) + A(x)}{2F_0(x)} \pmod {x^n} \end{eqnarray*}$$

$F_0$是在$\pmod {x^{\frac{n}{2}}}$意义下的结果

$$$$\label{quadratic}x^2 \equiv a \pmod p~~(p \nmid a)$$$$

## 多项式对数与多项式$exp$

### 麦克劳林级数

$$\sum ^{\infty }_{n=0}\dfrac {f^{n}\left( 0\right) }{n!}x^{n}$$

### 对数的计算

$$\ln (1 - A(x)) = -\sum_{i \geq 1} \frac{A^i(x)}{i}$$

$$lnA(x)=\int (lnA(x))'=\int\frac{A'(x)}{A(x)}$$

$f(g(x))=f’(g(x))g’(x)$

### 多项式exp

$$\exp(A(x)) = e^{A(x)} = \sum_{i \geq 0} \frac{A^i(x)}{i!}$$

$$lnF(x) = A(x)$$

$$\begin{eqnarray*} F(x) & \equiv & F_0(x) - \frac{G(F_0(x))}{G'(F_0(x))} \\ & \equiv & F_0(x) \left (1 - \ln F_0(x) + A(x) \right ) \pmod {x^n}\end{eqnarray*}$$

## 多项式幂函数

$$A^k(x)\pmod{x^n}$$

$$A^k(x)\equiv e^{klnA(x)}\pmod{x^n}$$

## 多项式三角函数

$$e^{iA(x)}=cos(A(x))+isin(A(x))$$

## 多项式的快速差值与多点求值

### 快速差值

$$\forall (x, y) \in X, A(x) = y$$

### 多点求值

$$\begin{eqnarray*} X^{[0]} &=& \{x_0, x_1, \cdots, x_{\lfloor \frac{n}{2} \rfloor}\} \\ X^{[1]} &=& \{x_{\lfloor \frac{n}{2} \rfloor+1},x_{\lfloor \frac{n}{2} \rfloor+2}, \cdots, x_{n-1}\} \end{eqnarray*}$$

$$\begin{eqnarray*} P^{[0]}(x) &=& \prod_{i=0}^{\lfloor \frac{n}{2} \rfloor} (x-x_i) \end{eqnarray*}$$

$$A(x) = D(x)P^{[0]}(x) + A^{[0]}(x)$$

$$A^{[0]}(x) \equiv A(x) \pmod {P^{[0]}(x)}$$

### 快速插值

$O(N^2)$：

$${A(x)=\sum_{i=1}^n{\frac{\prod_{{j}\neq{i}}{({x}-{x_j})}}{\prod_{{j}\neq{i}}{({x_i}-{x_j})}}{y_i}}}$$

$$\begin{eqnarray*} X^{[0]} &=& \{(x_i, y_i) : 0 \leq i \leq \lfloor \frac{n}{2} \rfloor \} \\ X^{[1]} &=& \{(x_i, y_i) : \lfloor \frac{n}{2} \rfloor < i \leq n\} \end{eqnarray*}$$

$$P(x) = \prod_{i=0}^{\lfloor \frac{n}{2} \rfloor} (x-x_i)$$

$$A(x) = A^{[1]}(x)P(x) + A^{[0]}(x)$$

$\forall (x_i, y_i) \in X^{[1]}, y_i = A^{[1]}(x_i)P(x_i) + A^{[0]}(x_i)$化简之后得到

$$A^{[1]}(x_i) = \frac{A^{[0]}(x_i)-y_i}{P(x_i)}$$

$T(n) = 2T(\frac{n}{2}) + \mathcal O(n \log^2 n) = \mathcal O(n \log^3 n)$

posted @ 2018-06-06 10:09  自为风月马前卒  阅读(...)  评论(...编辑  收藏

……