文章目录
任意模数NTT
Description
给定两个长度分别为 n , m n,m n,m的多项式F, G,请求出F与G的卷积。各项系数对模数 p p p取模。
请注意, p p p不一定是NTT模数。
n , m ≤ 1 0 5 n,m \le 10^5 n,m≤105
Solution
由于篇幅能力原因,这里仅介绍一种十分容易理解的方法。
我们任意取 3 3 3 个 1 0 9 10^9 109 级别的NTT模数,分别做一遍NTT,从而对于卷积式中的每一项系数 r e s i res_i resi 都有三个形如 r e s i ≡ k i , j ( m o d p i , j ) res_i \equiv k_{i,j}(mod\ p_{i,j}) resi≡ki,j(mod pi,j) 的表达式。
然后我们对于每一个 i i i 分别跑模意义下的CRT(中国剩余定理)即可得到每一项系数。
为什么这么做是有正确性的呢? 因为,不在模意义下的卷积的各项系数最大不超过 1 0 23 10^{23} 1023 ,而这三个NTT模数的最小公倍数就已经达到了 1 0 27 10^{27} 1027 。所以并不会出现哈希冲突。
时间复杂度 O ( n log n ) O(n \log n) O(nlogn) 。常数巨大。
分治NTT
Description
给定序列 g 1 , 2 , ⋯ n − 1 g_{1,2,\cdots n-1} g1,2,⋯n−1 ,现在需要你求出序列 f 0 , 1 , 2 , ⋯ , n − 1 f_{0,1,2,\cdots,n-1} f0,1,2,⋯,n−1 。
其中 f i = ∑ j = 1 i f i − j g j f_i=\sum_{j=1}^i f_{i-j}\ g_j fi=∑j=1ifi−j gj ,边界为 f 0 = 1 f_0=1 f0=1 。
答案对 998244353 998244353 998244353 取模。
Solution
如果我们枚举 i i i,每次都求一遍卷积的话,时间复杂度为 O ( n 2 log n ) O(n^2 \log n) O(n2logn) 。甚至比暴力还要慢不少。
我们参考 CDQ分治 的思想,每次先向左半边递归,然后处理左半边对右半边的贡献,接着向右半边递归 ⋯ ⋯ \cdots \cdots ⋯⋯以此类推。
更具体地说,假设当前搜索的区间是 [ l , r ] [l,r] [l,r],左子区间为 [ l , m i d ] [l,mid] [l,mid],右子区间为 [ m i d + 1 , r ] [mid+1,r] [mid+1,r]。我们先递归处理左子区间 [ l , m i d ] [l,mid] [l,mid] 。考虑右子区间中的一个位置 i ( m i d + 1 ≤ i ≤ r ) i(mid+1 \le i \le r) i(mid+1≤i≤r),它从左半边得到的贡献为 ∑ l ≤ j ≤ m i d f j g i − j \sum_{l \le j \le mid}f_j\ g_{i-j} ∑l≤j≤midfj gi−j 。不难发现,这是一个卷积的形式,于是大力 NTT 即可。
更为具体地说,每次考虑“左半边对右半边的贡献”的时候,所用到的 g g g 一定是前 r − l r-l r−l 个位置, f f f 用到的是区间 [ l , m i d ] [l,mid] [l,mid],直接将这些位置对应的多项式求卷积,得到的多项式对应的是区间 [ m i d + 1 , r ] [mid+1,r] [mid+1,r](即 r − m i d r-mid r−mid个位置)。于是我们把 f f f 中的那 m i d − l + 1 mid-l+1 mid−l+1 个位置映射到另一个数组里面,将它与 g g g 的对应区间做卷积,即可得到右半边的所有位置被左半边的贡献量。
令时间复杂度为 T ( n ) T(n) T(n) ,则有 T ( n ) = n log n + 2 T ( n 2 ) = O ( n log 2 n ) T(n)=n \log n+2T(\frac n 2)=O(n \log^2 n) T(n)=nlogn+2T(2n)=O(nlog2n)。
多项式求逆
Description
给定一个多项式 A A A,请你找到一个多项式 B B B,使得 A × B ≡ 1 ( m o d x n ) A×B \equiv 1(mod\ x^n) A×B≡1(mod xn)。
保证 A A A 的常数项为 1 1 1 。
Solution
假设我们已经求得了 A × B ′ ≡ 1 ( m o d x n 2 ) A×B' \equiv 1(mod\ x^{\frac n 2}) A×B′≡1(mod x2n),那么
A
×
(
B
−
B
′
)
≡
0
(
m
o
d
x
n
2
)
A×(B-B') \equiv 0(mod\ x^{\frac n 2})
A×(B−B′)≡0(mod x2n)
(
B
−
B
′
)
≡
0
(
m
o
d
x
n
2
)
(B-B') \equiv 0(mod\ x^{\frac n 2})
(B−B′)≡0(mod x2n)
B
2
−
2
B
B
′
+
B
′
2
≡
0
(
m
o
d
x
n
2
)
B^2-2BB'+B'^2 \equiv 0(mod\ x^{\frac n 2})
B2−2BB′+B′2≡0(mod x2n)
两边同时乘 A A A,得到
A
B
2
−
2
A
B
B
′
+
A
B
′
2
≡
0
(
m
o
d
x
n
2
)
AB^2-2ABB'+AB'^2 \equiv 0(mod\ x^{\frac n 2})
AB2−2ABB′+AB′2≡0(mod x2n)
B
−
2
B
′
+
A
B
′
2
≡
0
(
m
o
d
x
n
2
)
B-2B'+AB'^2 \equiv 0(mod\ x^{\frac n 2})
B−2B′+AB′2≡0(mod x2n)
B
≡
2
B
′
−
A
B
′
2
(
m
o
d
x
n
2
)
B \equiv 2B'-AB'^2(mod\ x^{\frac n 2})
B≡2B′−AB′2(mod x2n)
B
≡
B
′
(
2
−
A
B
′
)
(
m
o
d
x
n
2
)
B \equiv B'(2-AB')(mod\ x^{\frac n 2})
B≡B′(2−AB′)(mod x2n)
于是我们分治下去求 B ′ B' B′,回溯的时候用NTT求出 B ′ ( 2 − A B ′ ) B'(2-AB') B′(2−AB′)即可。
令时间复杂度为 T ( n ) T(n) T(n),则有 T ( n ) = T ( n 2 ) + n log n = O ( n log n ) T(n)=T(\frac n 2)+n \log n=O(n \log n) T(n)=T(2n)+nlogn=O(nlogn)。
多项式除法
Description
Solution
一种错误的做法是: 求出 B B B的逆元(即多项式的逆)然后用C去乘上它,即为 A A A。
对于这一种做法错误的原因主要是: 我们忽略了余数R的影响,导致可能不满足第一个条件。
于是我们想要避免余项R的影响。
令 F ( x ) ′ = x n F ( 1 x ) F(x)'=x^n F(\frac 1 x) F(x)′=xnF(x1),其中 n n n为多项式 F F F的项数(虽然 ′ ' ′已经表示了求导,但是这里暂时借用一下)。
不难发现, F ( x ) ′ F(x)' F(x)′的各项系数与 F ( x ) F(x) F(x)的各项系数恰好相反。
我们开始愉快地推式子:
F
(
x
)
=
Q
(
x
)
G
(
x
)
+
R
(
x
)
F(x)=Q(x)G(x)+R(x)
F(x)=Q(x)G(x)+R(x)
F
(
x
)
=
x
n
−
m
Q
(
1
x
)
x
m
G
(
1
x
)
+
x
n
−
m
+
1
x
m
−
1
R
(
x
)
F(x)=x^{n-m}Q(\frac 1 x)\ x^mG(\frac 1 x)+x^{n-m+1}\ x^{m-1} R(x)
F(x)=xn−mQ(x1) xmG(x1)+xn−m+1 xm−1R(x)
F
′
(
x
)
=
Q
′
(
x
)
G
′
(
X
)
+
x
n
−
m
+
1
R
′
(
x
)
F'(x)=Q'(x)G'(X)+x^{n-m+1}R'(x)
F′(x)=Q′(x)G′(X)+xn−m+1R′(x)
此时,在模 x n − m + 1 x^{n-m+1} xn−m+1的意义下, R ′ R' R′的影响被消除了!于是我们可以直接多项式求逆+多项式乘法求出 Q ′ Q' Q′,然后翻转得到 Q Q Q,最后一步一步回带即可。
时间复杂度 O ( n log n ) O(n \log n) O(nlogn)。
多项式ln(对数函数)
Description
给定一个多项式 A ( n ) A(n) A(n),请找到一个多项式 B ( x ) B(x) B(x)使得 B ( x ) ≡ ln A ( x ) ( m o d x n ) B(x) \equiv \ln A(x)(mod\ x^n) B(x)≡lnA(x)(mod xn)
前置芝士
导数
导数的基本定义不讲了,毕竟高中数学课本上有(
这里重点介绍几个公式:
①
(
p
G
(
x
)
)
′
=
p
G
′
(
x
)
(p\ G(x))'=p\ G'(x)
(p G(x))′=p G′(x)
②
(
n
m
)
′
=
m
n
m
−
1
(n^m)'=mn^{m-1}
(nm)′=mnm−1。
根据①②,我们学会了多项式求导:
void qiudao(int *A,int *res,int len){
for (int i=1;i<=len;i++) res[i-1]=(i*A[i])%mod;
res[len-1]=0;
}
③ ( n m ) ( m ) = m ! (n^m)^{(m)}=m! (nm)(m)=m! 。虽然这个公式在多项式求 ln \ln ln中的用处并不大,但是泰勒展开中需要它。
积分
积分就是“逆导数”。例如, 2 x 2x 2x的积分是 x 2 x^2 x2。
这里重点介绍一个公式:
④
a
x
n
ax^n
axn的积分是
a
n
+
1
x
n
+
1
\frac {a} {n+1}x^{n+1}
n+1axn+1。
证明: 由于
x
n
+
1
x^{n+1}
xn+1的导数是
(
n
+
1
)
x
n
(n+1) {x^n}
(n+1)xn,所以
a
n
+
1
x
n
+
1
\frac {a} {n+1}x^{n+1}
n+1axn+1的导数就是
a
x
n
ax^{n}
axn。
于是我们也学会了多项式积分:
void jifen(int *A,int *res,int len){
for (int i=1;i<=len;i++) res[i]=(A[i-1]*ny(i))%mod;
res[0]=0;
}
Solution
根据 B ( x ) ≡ ln A ( x ) ( m o d x n ) B(x) \equiv \ln A(x)(mod\ x^n) B(x)≡lnA(x)(mod xn)
等式两边同时求导得 B ′ ( x ) ≡ A ( x ) ′ A ( x ) ( m o d x n ) B'(x) \equiv \frac {A(x)'} {A(x)}(mod\ x^n) B′(x)≡A(x)A(x)′(mod xn)
于是我们先将 A ( x ) A(x) A(x)求导得到 A ( x ) ′ A(x)' A(x)′,然后求出 A ( x ) A(x) A(x)的逆元得到 1 A ( x ) \frac 1 {A(x)} A(x)1,再将这两个多项式相乘得到 B ′ ( x ) B'(x) B′(x),最后积分回去即可。
时间复杂度 O ( n log n ) O(n \log n) O(nlogn)。
多项式牛顿迭代
Description
给定多项式 G G G,请你找到多项式 F F F使得 G ( F ( x ) ) ≡ 0 ( m o d x n ) G(F(x)) \equiv 0(mod\ x^n) G(F(x))≡0(mod xn)。
前置芝士: 泰勒展开
泰勒展开不会的话请自己学,我不想写 笔者只放一个套路式:
G ( x ) = ∑ i = 0 ∞ G ( i ) ( a ) i ! ( x − a ) i G(x)=\sum_{i=0}^{∞} \frac {G^{(i)}(a)} {i!} (x-a)^i G(x)=∑i=0∞i!G(i)(a)(x−a)i
Solution
这里的 G , F G,F G,F分别是两个多项式函数。例如当 G ( x ) = x + 2 , f ( x ) = x − 1 G(x)=x+2,f(x)=x-1 G(x)=x+2,f(x)=x−1时,那么 G ( F ( 15 ) ) = G ( 14 ) = 16 G(F(15))=G(14)=16 G(F(15))=G(14)=16。
假设我们已经求出了 G ( F 0 ( x ) ) ≡ 0 ( m o d x n 2 ) G(F_0(x)) \equiv 0(mod\ x^{\frac n 2}) G(F0(x))≡0(mod x2n)。
我们考虑将这个式子在 x x x处泰勒展开。根据Part 2中的公式,不难得到
G ( F ( x ) ) ≡ ∑ i = 0 ∞ G ( i ) ( F 0 ( x ) ) i ! ( F ( x ) − F 0 ( x ) ) i ( m o d x n ) G(F(x)) \equiv \sum_{i=0}^{∞} \frac {G^{(i)}(F_0(x))} {i!} (F(x)-F_0(x))^i(mod\ x^n) G(F(x))≡i=0∑∞i!G(i)(F0(x))(F(x)−F0(x))i(mod xn)
对于右式而言,
∑
i
=
0
∞
G
(
i
)
(
F
(
x
)
)
i
!
(
x
−
a
)
i
(
m
o
d
x
n
)
\sum_{i=0}^{∞} \frac {G^{(i)}(F(x))} {i!} (x-a)^i(mod\ x^n)
∑i=0∞i!G(i)(F(x))(x−a)i(mod xn)
≡
G
(
F
0
(
x
)
)
+
G
′
(
F
0
(
x
)
)
(
F
(
x
)
−
F
0
(
x
)
)
\equiv G(F_0(x))+G'(F_0(x))(F(x)-F_0(x))
≡G(F0(x))+G′(F0(x))(F(x)−F0(x))
为什么 G ( F ( x ) ) G(F(x)) G(F(x))的泰勒展开式的高于一次项都被消去了呢?因为
G ( F ( x ) ) ≡ 0 ( m o d x n 2 ) G(F(x)) \equiv 0(mod\ x^{\frac n 2}) G(F(x))≡0(mod x2n)
G ( F 0 ( x ) ) ≡ 0 ( m o d x n 2 ) G(F_0(x)) \equiv 0(mod\ x^{\frac n 2}) G(F0(x))≡0(mod x2n)
两式相减得
G
(
F
(
x
)
)
−
G
(
F
0
(
x
)
)
≡
0
(
m
o
d
x
n
2
)
G(F(x))-G(F_0(x)) \equiv 0(mod\ x^{\frac n 2})
G(F(x))−G(F0(x))≡0(mod x2n)
于是,对于 ( G ( F ( x ) ) − G ( F 0 ( x ) ) ) p (G(F(x))-G(F_0(x)))^p (G(F(x))−G(F0(x)))p而言,若 2 ≤ p 2 \le p 2≤p,那么必然有
G ( F ( x ) ) − G ( F 0 ( x ) ) ≡ 0 ( m o d x n ) G(F(x))-G(F_0(x)) \equiv 0(mod\ x^n) G(F(x))−G(F0(x))≡0(mod xn)
所以高次项都被消除了。
我们回到刚才的式子
G
(
F
(
x
)
)
≡
G
(
F
0
(
x
)
)
+
G
′
(
F
0
(
x
)
)
(
F
(
x
)
−
F
0
(
x
)
)
(
m
o
d
x
n
)
G(F(x)) \equiv G(F_0(x))+G'(F_0(x))(F(x)-F_0(x)) (mod\ x^n)
G(F(x))≡G(F0(x))+G′(F0(x))(F(x)−F0(x))(mod xn)
我们让需要求的
G
(
F
(
x
)
)
G(F(x))
G(F(x))放到一边,于是随便整理一波得到
F
(
x
)
=
F
0
(
x
)
−
G
(
F
0
(
x
)
)
G
′
(
F
0
(
x
)
)
F(x)=F_0(x)-\frac {G(F_0(x))} {G'(F_0(x))}
F(x)=F0(x)−G′(F0(x))G(F0(x))
于是直接分治下去就行了。
令时间复杂度为 T ( n ) T(n) T(n),则 T ( n ) = n log n + T ( n 2 ) = n log n T(n)=n \log n+T(\frac n 2)=n \log n T(n)=nlogn+T(2n)=nlogn。
应用
这个东西的应用极其广泛。比如它可以直接解决多项式求逆。
令 G ( F ( x ) ) = F ( x ) − 1 − A ( x ) G(F(x))=F(x)^{-1}-A(x) G(F(x))=F(x)−1−A(x)。根据多项式求逆的定义,显然 G ( F ( x ) ) ≡ 0 ( m o d x n ) G(F(x)) \equiv 0(mod\ x^n) G(F(x))≡0(mod xn)。
所以 F ( x ) = F 0 ( x ) − F 0 ( x ) − 1 − A ( x ) − F 0 ( x ) − 2 F(x)=F_0(x)-\frac {F_0(x)^{-1}-A(x)} {-F_0(x)^{-2}} F(x)=F0(x)−−F0(x)−2F0(x)−1−A(x)
即 F ( x ) = 2 F 0 ( x ) − F 0 ( x ) 2 A ( x ) F(x)=2F_0(x)-F_0(x)^2\ A(x) F(x)=2F0(x)−F0(x)2 A(x)
多项式开根
Description
给定一个多项式 A A A,请你找到多项式 B B B使得 B 2 ( x ) ≡ A ( x ) ( m o d x n ) B^2(x) \equiv A(x) (mod\ x^n) B2(x)≡A(x)(mod xn)。
Solution
建议读者把它当成一道题而不是一个模板来做,由此训练一下多项式牛顿迭代的函数构造以及推导整理能力。
令 G ( F ( x ) ) = F ( x ) 2 − A ( x ) G(F(x))=F(x)^2-A(x) G(F(x))=F(x)2−A(x)
则 F ( x ) ≡ F 0 ( x ) − F 0 ( x ) 2 − A ( x ) 2 F 0 ( x ) ( m o d x n ) F(x) \equiv F_0(x)-\frac {F_0(x)^2-A(x)} {2F_0(x)}(mod\ x^n) F(x)≡F0(x)−2F0(x)F0(x)2−A(x)(mod xn)
整理得 F ( x ) = A ( x ) 2 F 0 ( x ) + F 0 ( x ) 2 F(x)=\frac {A(x)} {2F_0(x)}+\frac {F_0(x)} {2} F(x)=2F0(x)A(x)+2F0(x)
于是我们分治下去,回溯的时候,求一下 F 0 ( x ) F_0(x) F0(x)的逆元,再用 A ( x ) A(x) A(x)乘上它并加上 F 0 ( x ) F_0(x) F0(x),然后除以 2 2 2即可。
时间复杂度 O ( n log n ) O(n \log n) O(nlogn)。
多项式exp(指数函数)
Description
给定多项式 A ( x ) A(x) A(x),请你求出多项式 B ( x ) B(x) B(x)使得 e A ( x ) ≡ B ( x ) ( m o d x n ) e^{A(x)} \equiv B(x)(mod\ x^n) eA(x)≡B(x)(mod xn)。
Solution
等式两边同时 ln \ln ln得 ln B ( x ) ≡ A ( x ) ( m o d x n ) \ln B(x) \equiv A(x)(mod\ x^n) lnB(x)≡A(x)(mod xn)
令 G ( F ( x ) ) = ln F ( x ) − A ( x ) G(F(x))=\ln F(x)-A(x) G(F(x))=lnF(x)−A(x),不难得到 G ( B ( x ) ) ≡ 0 ( m o d x n ) G(B(x)) \equiv 0(mod\ x^n) G(B(x))≡0(mod xn),于是我们就可以快乐地牛顿迭代了。
F
(
x
)
=
F
0
(
x
)
−
ln
F
0
(
x
)
−
A
(
x
)
F
0
′
(
x
)
F
0
(
x
)
F(x)=F_0(x)-\frac {\ln F_0(x)-A(x)}{\frac {F_0'(x)} {F_0(x)}}
F(x)=F0(x)−F0(x)F0′(x)lnF0(x)−A(x)
=
F
0
(
x
)
−
ln
F
0
(
x
)
−
A
(
x
)
1
F
0
(
x
)
=F_0(x)-\frac {\ln F_0(x)-A(x)}{\frac {1} {F_0(x)}}
=F0(x)−F0(x)1lnF0(x)−A(x)
=
F
0
(
x
)
(
1
−
ln
F
0
(
x
)
+
A
(
x
)
)
=F_0(x)(1-\ln F_0(x)+A(x))
=F0(x)(1−lnF0(x)+A(x))
递归下去,回溯时做一遍多项式 ln \ln ln与多项式乘法即可。
时间复杂度 O ( n log n ) O(n \log n) O(nlogn)。
多项式快速幂
Description
给定多项式 A ( x ) A(x) A(x) 与 p p p,请求出多项式 B ( x ) B(x) B(x) 使得 B ( x ) ≡ A ( x ) p ( m o d x n ) B(x) \equiv A(x)^p(mod\ x^n) B(x)≡A(x)p(mod xn)。
Solution
首先,一种方法是快速幂套多项式乘法,时间复杂度是 O ( n log n log p ) O(n \log n \log p) O(nlognlogp)的。
考虑如何优化。不难发现 x = e ln x x=e^{\ln x} x=elnx,所以 B ( x ) ≡ e p ln A ( x ) B(x) \equiv e^{p\ln A(x)} B(x)≡eplnA(x)。
于是我们求出 ln A ( x ) \ln A(x) lnA(x),将各项系数乘 p p p 然后再 exp \exp exp 求出 e p ln A ( x ) e^{p \ln A(x)} eplnA(x) 即为答案。
完整模板
int n,k;
int a[maxl],b[maxl],rev[maxl];
int quick_power(int x,int y){
int res=1;
for (;y;y=y>>1,x=(x*x)%mod){
if (y&1) res=(res*x)%mod;
}
return res;
}
int ny(int tmpxtmpxxx){return quick_power(tmpxtmpxxx,mod-2);}
namespace poly{
int tmp[maxl],f[maxl],g[maxl];
void NTT(int *A,int len,int flag){
for (rg int i=0;i<len;++i){
if (i>rev[i]) swap(A[i],A[rev[i]]);
}
for (rg int i=2;i<=len;i*=2){
int wn;
if (flag==1) wn=quick_power(G,(mod-1)/i);
else wn=quick_power(Gi,(mod-1)/i);
for (int j=0;j<len;j+=i){
int w=1;
for (rg int k=j;k<j+(i/2);k++){
int u=A[k],v=(w*A[k+(i/2)])%mod;
A[k]=(u+v)%mod,A[k+(i/2)]=(u+mod-v)%mod;
w=(w*wn)%mod;
}
}
}
if (flag==-1){
int ducati_cai=quick_power(len,mod-2);
for (int i=0;i<len;++i) A[i]=(A[i]*ducati_cai)%mod;
}
}
void Mul(int *A,int *B,int *C,int n,int m){
int F[maxl],G[maxl];
int p=1,cnt=0;
while (p<=n+m) p*=2,cnt++;
for (int i=0;i<=p;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
for (int i=0;i<=n;++i) F[i]=A[i];
for (int i=0;i<=m;++i) G[i]=B[i];
for (int i=n+1;i<=p;++i) F[i]=0;
for (int i=m+1;i<=p;++i) G[i]=0;
NTT(F,p,1),NTT(G,p,1);
for (rg int i=0;i<=p;++i) C[i]=(F[i]*G[i])%mod;
NTT(C,p,-1);
}
void get_inv(int *A,int *res,int len){
if (len==1){
res[0]=quick_power(A[0],mod-2);
return;
}
get_inv(A,res,(len+1)>>1);
int p=1,cnt=0;
while (p<=len<<1) p<<=1,cnt++;
for (rg int i=0;i<=p;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
for (int i=0;i<=len;++i) tmp[i]=A[i];
for (int i=len;i<=p;++i) tmp[i]=0;
NTT(tmp,p,1),NTT(res,p,1);
for (rg int i=0;i<=p;++i) res[i]=(((2-res[i]*tmp[i])%mod+mod)%mod*res[i])%mod;
NTT(res,p,-1);
for (int i=len;i<=p;++i) res[i]=0;
}
void Divide(int *A,int *B,int *D,int *R,int n,int m){
int invb[maxl],dtmp[maxl];
reverse(B+1,B+m+1),reverse(A+1,A+n+1);
get_inv(B,invb,n-m+1),Mul(A,invb,D,n-m,n-m);
reverse(A+1,A+n+1),reverse(B+1,B+m+1),reverse(D+1,D+n-m+1);
Mul(B,D,dtmp,m,n-m);
for (int i=0;i<m;++i) R[i]=(A[i]-dtmp[i]+mod)%mod;
}
void get_mod(int *A,int *B,int *R,int n,int m){Divide(A,B,tmp,R,n,m);}
void qiudao(int *A,int *res,int len){
for (int i=1;i<len;++i) res[i-1]=(A[i]*i)%mod;
res[len-1]=0;
}
void jifen(int *A,int *res,int len){
for (int i=1;i<len;++i) res[i]=(A[i-1]*ny(i))%mod;
res[0]=0;
}
void get_ln(int *A,int *res,int len){
int inva[maxl],da[maxl],mul_num[maxl];
memset(inva,0,sizeof(inva));
get_inv(A,inva,len);
qiudao(A,da,len);
Mul(inva,da,mul_num,len,len);
jifen(mul_num,res,len);
}
void get_exp(int *A,int *res,int len){
if (len==1){
res[0]=1;
return;
}
get_exp(A,res,(len+1)>>1);
int p=1,cnt=0;
while (p<=len<<1) p<<=1,cnt++;
for (rg int i=0;i<p;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
for (int i=0;i<len;++i) g[i]=A[i];
for (int i=len;i<p;++i) g[i]=0;
for (int i=0;i<p;++i) f[i]=0;
get_ln(res,f,len);
NTT(g,p,1),NTT(f,p,1),NTT(res,p,1);
for (rg int i=0;i<p;++i) res[i]=((1-f[i]+g[i]+mod)%mod*res[i])%mod;
NTT(res,p,-1);
for (int i=len;i<p;++i) res[i]=0;
}
void get_pow(int *A,int *res,int len,int k){
int C[maxl];
get_ln(A,C,len);
for (int i=0;i<len;++i) C[i]=(C[i]*k)%mod;
get_exp(C,res,len);
}
};
学会了这些多项式的算法之后,我们来看看这些算法的广大应用。