多项式学习笔记[二](全网最详细!有图有代码有解释有例题有总结!)

上篇

任意模数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,m105

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}) resiki,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,n1 ,现在需要你求出序列 f 0 , 1 , 2 , ⋯   , n − 1 f_{0,1,2,\cdots,n-1} f0,1,2,,n1

其中 f i = ∑ j = 1 i f i − j   g j f_i=\sum_{j=1}^i f_{i-j}\ g_j fi=j=1ifij 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+1ir),它从左半边得到的贡献为 ∑ l ≤ j ≤ m i d f j   g i − j \sum_{l \le j \le mid}f_j\ g_{i-j} ljmidfj gij 。不难发现,这是一个卷积的形式,于是大力 NTT 即可。

更为具体地说,每次考虑“左半边对右半边的贡献”的时候,所用到的 g g g 一定是前 r − l r-l rl 个位置, 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 rmid个位置)。于是我们把 f f f 中的那 m i d − l + 1 mid-l+1 midl+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×B1(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×B1(mod x2n),那么

A × ( B − B ′ ) ≡ 0 ( m o d   x n 2 ) A×(B-B') \equiv 0(mod\ x^{\frac n 2}) A×(BB)0(mod x2n)
( B − B ′ ) ≡ 0 ( m o d   x n 2 ) (B-B') \equiv 0(mod\ x^{\frac n 2}) (BB)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}) B22BB+B20(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}) AB22ABB+AB20(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}) B2B+AB20(mod x2n)
B ≡ 2 B ′ − A B ′ 2 ( m o d   x n 2 ) B \equiv 2B'-AB'^2(mod\ x^{\frac n 2}) B2BAB2(mod x2n)
B ≡ B ′ ( 2 − A B ′ ) ( m o d   x n 2 ) B \equiv B'(2-AB')(mod\ x^{\frac n 2}) BB(2AB)(mod x2n)

于是我们分治下去求 B ′ B' B,回溯的时候用NTT求出 B ′ ( 2 − A B ′ ) B'(2-AB') B(2AB)即可。

令时间复杂度为 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)=xnmQ(x1) xmG(x1)+xnm+1 xm1R(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)+xnm+1R(x)

此时,在模 x n − m + 1 x^{n-m+1} xnm+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)=mnm1
根据①②,我们学会了多项式求导:

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=0i!G(i)(a)(xa)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)=x1时,那么 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=0i!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=0i!G(i)(F(x))(xa)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 2p,那么必然有

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)1A(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)1A(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)2A(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)2A(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)(1lnF0(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);
	}
};

学会了这些多项式的算法之后,我们来看看这些算法的广大应用。

下篇

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值