牛顿迭代
若
G ( F 0 ( x ) ) ≡ 0 ( m o d x 2 t ) G(F_0(x))\equiv 0(mod\ x^{2^t}) G(F0(x))≡0(mod x2t)
牛顿迭代
F ( x ) ≡ F 0 ( x ) − G ( F 0 ( x ) ) G ′ ( F 0 ( x ) ) ( m o d x 2 t + 1 ) F(x)\equiv F_0(x)-\frac{G(F_0(x))}{G'(F_0(x))}(mod\ x^{2^{t+1}}) F(x)≡F0(x)−G′(F0(x))G(F0(x))(mod x2t+1)
以下多数都可以牛顿迭代公式一步得到
多项式求逆
给定 A ( x ) A(x) A(x)求满足 A ( x ) ∗ B ( x ) = 1 A(x)*B(x)=1 A(x)∗B(x)=1的 B ( x ) B(x) B(x)
写成
A ( x ) ∗ B ( x ) = 1 ( m o d x n ) A(x)*B(x)=1(mod \ x^n) A(x)∗B(x)=1(mod xn)
我们会求 A ( x ) ∗ B ( x ) = 1 ( m o d x 1 ) A(x)*B(x)=1(mod \ x^1) A(x)∗B(x)=1(mod x1)
然后我们考虑求 A ( x ) ∗ B ( x ) = 1 ( m o d x t ) A(x)*B(x)=1(mod \ x^t) A(x)∗B(x)=1(mod xt)
( A ( x ) ∗ B ( x ) − 1 ) 2 = 0 ( m o d x 2 t ) (A(x)*B(x)-1)^2=0(mod \ x^{2t}) (A(x)∗B(x)−1)2=0(mod x2t)
A ( x ) ( 2 B ( x ) − A ( x ) ∗ B 2 ( x ) ) = 1 ( m o d x 2 t ) A(x)(2B(x)-A(x)*B^2(x))=1(mod \ x^{2t}) A(x)(2B(x)−A(x)∗B2(x))=1(mod x2t)
把 2 B ( x ) − A ( x ) ∗ B 2 ( x ) 2B(x)-A(x)*B^2(x) 2B(x)−A(x)∗B2(x)当作新的 B B B倍增算
从 m o d x 1 mod \ x^1 mod x1倍增到大于等于 n n n
# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(4e5 + 5);
const int Zsy(998244353);
const int Phi(998244352);
const int G(3);
IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
}
IL int Pow(RG ll x, RG ll y){
RG ll ret = 1;
for(; y; x = x * x % Zsy, y >>= 1)
if(y & 1) ret = ret * x % Zsy;
return ret;
}
int N, r[_], l, A[_], B[_];
IL void NTT(RG int *P, RG int opt){
for(RG int i = 0; i < N; ++i) if(i < r[i]) swap(P[i], P[r[i]]);
for(RG int i = 1; i < N; i <<= 1){
RG int wn = Pow(G, Phi / (i << 1));
if(opt == -1) wn = Pow(wn, Zsy - 2);
for(RG int j = 0, p = i << 1; j < N; j += p)
for(RG int w = 1, k = 0; k < i; w = 1LL * w * wn % Zsy, ++k){
RG int X = P[k + j], Y = 1LL * w * P[k + j + i] % Zsy;
P[k + j] = (X + Y) % Zsy, P[k + j + i] = (X - Y + Zsy) % Zsy;
}
}
}
IL void Mul(RG int *a, RG int *b, RG int len){
for(l = 0, N = 1, len += len - 1; N <= len; N <<= 1) ++l;
for(RG int i = 0; i < N; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
for(RG int i = 0; i < N; ++i) A[i] = B[i] = 0;
for(RG int i = 0; i <= len >> 1; ++i) A[i] = a[i], B[i] = b[i];
NTT(A, 1), NTT(B, 1);
for(RG int i = 0; i < N; ++i