多项式:从什么都不知道到门都没入

多项式

单项式:由数字和字母组成的积的代数式称为单项式

多项式:由若干个单项式相加组成的代数式叫做多项式

废话,这上过初中的人都知道

一、一元多项式

(nin N^*),则我们称多项式

[a_nx^n+a_{n-1}x^{n-1}+...+a_1x+a_0 ]

一元多项式

其中,我们称(a_ix^i)(i)次项,(a_i)(i)次项系数。

两个多项式(f(x))(g(x))相等,当且仅当它们同次项的系数相等。

(a_n ot= 0),则我们称(a_n)为多项式的首项,(n)为多项式的次数,记为(deg) (f)

二、 多项式的基本运算

1.加法与乘法运算

[f(x)=a_nx^n+a_{n-1}x^{n-1}+...+a_1x+a_0\ g(x)=b_nx^n+b_{n-1}x^{n-1}+...+b_1x+b_0 ]

[f(x)+g(x)=(a_n+b_n)x^n+(a_{n-1}+b_{n-1})x^{n-1}+...+(a_1+b_1)x+a_0+b_0\ f(x) imes g(x)=a_nb_nx^{2n}+...+sum_{i=0}^n a_{n-i}b_i x^n+...+a_1b_1x+a_0b_0 ]

多项式的加法和乘法满足交换律和结合律,乘法还满足分配律

2.带余除法

(f(x))(g(x))是的两个多项式,且(g(x))不等于0,则有唯一的多项式 (q(x))(r(x)),满足

[f(x)=q(x)g(x)+r(x) ]

其中(r(x))的次数小于(g(x))的次数。

此时,

(q(x)) 称为(g(x))(ƒ(x))的商式。

(r(x))称为余式。

(r(x)=0),则我们称(g(x))(f(x))的因式

多项式的带余除法不是本文研究的重点,有兴趣的可以自行查阅资料

三、关于多项式的几个重要定理

1.代数基本定理

任何复系数一元n次多项式方程在复数域上至少有一根。

代数基本定理在数学中的运用十分广泛。

2.唯一分解定理

数域(P)上的每个次数大于零的多项式(f(x))都可以分解为数域(P)上的不可约多项式的乘积

这与算术基本定理十分相似。

3.高斯引理

本原多项式:若多项式(a_nx^n+a_{n-1}x^{n-1}+...+a_1x+a_0)满足(gcd(a_1,a_2,...,a_n)=1),则我们称该多项式为本原多项式

高斯引理: 两个本原多项式的积是本原多项式

这些引理的应用是数学竞赛的范围了,有兴趣的可以自行了解。

四、多项式的零点

若有一数(a)使得多项式(f(x)=0),则我们称(a)为多项式(x)的零点。

这里我们有两个重要的定理:

1.余式定理

(f(x))除以(x-a)的余式是(f(a))

证明:
(g(x))为商式,(r(x))为余式,则我们有:

[f(x)=(x-a)g(x)+r(x) ]

(x=a)代入得:

[f(a)=(a-a)g(a)+r(a)=r(a) ]

证毕。

余式定理的几个推论:

1.因式定理

如果多项式(f(a)=0),那么多项式(f(x))必定含有因式(x-a)

2.多项式(a_nx^n+a_{n-1}x^{n-1}+...+a_1x+a_0)至多有(n)个不同的零点。

用反证法可以证明,这里略去。

3.如果多项式(a_nx^n+a_{n-1}x^{n-1}+...+a_1x+a_0)至少有(n+1)个零点,那么该多项式为(0)

如果此时他不是(0),则他至多有(n)个零点,由(2)导出矛盾。

2.恒等定理

若有无穷多个(a)使得(f(a)=g(a)),则(f(x)=g(x))

(h(x)=f(x)-g(x)),因为此时(h(x))有无穷多个零点,由上面的第3个结论可知,(h(x)=0)

看到这里,可能很多人不耐烦了:

我们是OIer,你给我们讲那么多这些玩意干什么?

如果上面是纯数学竞赛内容的话,那么下面就是数竞与信竞的交集了。

--------------------------------------------------------------分割线------------------------------------------------------------------------------------

五、多项式的插值与差分

(注意:本章将涉及到一些OI中的知识,数竞党看不懂可略过)

我们回到多项式乘法。

如果我们暴力乘两个(n)次多项式,那么时间复杂度将是(O(n^2))

那么我们可不可以对一般的多项式乘法进行些优化呢?

我们可以通过改变运算顺序(CPU的运算原理相关)来优化,但我们最多只能优化些常数因子罢了

如果我们不能跳出上面的思维局限,那么我们不可能在根本上优化算法的时间复杂度

我们得换个角度观察问题。

在平面直角坐标系中,我们给出平面上(n)个不同的点:

[(x_1,y_1),(x_2,y_2),...,(x_n,y_n) ]

那么,我们能否找到一条曲线,使得该曲线穿过这些点呢?

换言之,我们希望找到一个函数(f(x)),使得:

[f(x_1)=y_1\ f(x_2)=y_2\ ...\ f(x_n)=y_n ]

但显然,这样的函数有无数个。

一般而言,多项式函数是这些函数中最简单的。

那么,多项式就有另外一种表示法:

多项式的点值表示法

我们用满足(f(x)=y)(n)个数对

[(x_1,y_1),(x_2,y_2),...,(x_n,y_n) ]

来表示一个(n-1)次多项式。

如果我们给定一个多项式,给出(n)组点值最简单的方法就是任选(n)个不同的(x_i),分别计算此时多项式的值

(n)个点值对也可以唯一确定一个不超过(n-1)次多项式,这个过程称为插值

于是,一个著名的公式出现了:

拉格朗日插值公式

对于多项式的点值

[(x_0,y_0),(x_1,y_1),...,(x_{n-1},y_{n-1}) ]

存在一个唯一的不超过(n-1)次的多项式(f(x)),并且(f(x))可以表示为:

[f(x)=y_0frac{(x-x_1)(x-x_2)...(x-x_{n-1})}{(x_0-x_1)(x_0-x_2)...(x_0-x_{n-1})}\ +y_1frac{(x-x_0)(x-x_2)...(x-x_{n-1})}{(x_1-x_0)(x_1-x_2)...(x_2-x_{n-1})}+...\ +y_{n-1}frac{(x-x_0)(x-x_1)...(x-x_{n-2})}{(x_{n-1}-x_0)(x_{n-1}-x_1)...(x_{n-1}-x_{n-2})} ]

整理的好看点:

[f(x)=sum_{i=0}^{n-1} y_i imes prod_{0leq i ot=jleq n-1} frac{x-x_j}{x_i-x_j} ]

为了证明插值公式,我们必须证明多项式插值的存在性和唯一性

存在性证明:

(这部分涉及一些线性代数的知识,如果实在不会可以略过)

(估计也只有我这种蒟蒻不怎么会线性代数)

我们可以把多项式的每个点值看成一个方程,那么我们就有了(n)个方程,它们组成了线性方程组。

我们把这个线性方程组改写成矩阵的形式:

[egin{bmatrix} 1&x_0& x_0^2 &cdots & x_0^{n-1} \ 1& x_1& x_1^2 &cdots & x_1^{n-1}\ vdots& vdots& vdots & ddots & vdots\ 1& x_{n-1} & x_{n-1}^2& cdots & x_{n-1}^{n-1} end{bmatrix} egin{bmatrix} a_0\ a_1\ vdots\ a_{n-1} end{bmatrix}= egin{bmatrix} y_0 \ y_1 \ vdots \ y_{n-1} end{bmatrix} ]

我们不妨记为(XA=Y)

该式可以转化为(A=X^{-1}Y)

因此我们只需要证明(X)有没有逆矩阵即可。

Q:什么是逆矩阵啊

A:若我们有(AB=E)(E)为单位矩阵),则我们称(B)(A)矩阵的逆

Q:单位矩阵又是啥啊

A:主对角线上全是1的举证就是单位矩阵。单位矩阵有一个性质,即任何矩阵乘单位矩阵都等于它本身

这里我们介绍一个东西:范德蒙行列式

线代julao可略过

长成上面这样的矩阵就是范德蒙矩阵了。

而范德蒙行列式是有它的特殊的计算公式的。

对于一个范德蒙矩阵,它的行列式的计算公式为:

[det(X)=prod _{1leq i<jleq n} (x_j-x_i) ]

显然,(x_j-x_i ot=0),所以矩阵的行列式值不等于0,即该矩阵有逆

唯一性证明:

如果有两个这样的多项式,那么它们的差就至少有(n)个不同的零点(点值中(y)值差为0),由上面余式定理的第三个推论可得,这个差值一定为0

正确性证明:

现在我们来看看拉格朗日插值公式是怎么构造这个多项式的。

在特殊情形(y_1=y_2=...=y_{n-1}=0)时,求出满足条件多项式(f_1(x))。这时,(f_1(x))(n-1)个不同的零点(x_1,x_2,...,x_{n-1}),根据因式定理,该多项式被((x-x_1)(x-x_2)...(x-x_{n-1}))整除。

我们有要求多项式的次数尽可能的低,故我们得到:

[f_1(x)=c(x-x_1)(x-x_2)...(x-x_{n-1}) ]

其中(c)是一个常数,由(f_1(x_0)=y_0)确定。

我们就有:

[f_1(x_0)=y_0=c(x_0-x_1)(x_0-x_2)...(x_0-x_{n-1}) ]

所以

[c=frac{y_0}{(x_0-x_1)(x_0-x_2)...(x_0-x_{n-1})} ]

于是

[f_1(x)=y_0frac{(x-x_1)(x-x_2)...(x-x_{n-1})}{(x_0-x_1)(x_0-x_2)...(x_0-x_{n-1})} ]

类似的,我们可以构造(f_i(x)),使得(f_i(x_i)=y_i)

显然,当(x ot=i)时((x)(x_0,x_1,...x_{n-1})中的任意一个),(f_i(x)=0)(因为分子总有一个因式值为0)

所以,这样的(f(x)=f_1(x)+f_2(x)+...f_n(x))满足条件。

优缺点

拉格朗日插值公式结构紧凑,十分优美,易于理解,在理论分析中十分方便。

然而,当一个插值点改变时,整个插值公式必须要重新计算。

解决方案就是使用重心拉格朗日插值法或者牛顿迭代法。

然而我太菜了,这两个方法我都不会。

还是得多多学习啊!

插值介绍完了,现在轮到差分了。

广大OIer对差分的影响,估计是这样的:

差分不就是和前缀和结合在一起用的东西吗!

树状数组区间修改用差分!(注:局限性很大)

树上差分!天天爱跑步!(明明线段树合并就解决了

多项式差分正是差分众多形式中的一种。

对于函数(f(x))和固定的(h ot=0)

[f(x+h)-f(x) ]

称为(f(x))步长为(h)的一阶差分,记作(Delta_h^1f(x))(Delta_h^1f(x))的差分

[egin{align} Delta_h^1f(x+h)-Delta_h^1f(x)&=(f(x+2h)-f(x+h))-(f(x+h)-f(x))\ &=f(x+2h)-2f(x+h)+f(x) end{align} ]

称为(f(x))的(步长为(h))的二阶差分,记作(Delta_h ^2f(x))

对于(f(x))(n)阶差分,我们有以下公式:

[Delta _h ^n f(x)=sum_{i=0}^n(-1)^{n-i}C_n^if(x+ih) ]

上述公式在(n=1)时显然成立,于是我们可以结合数学归纳法证明,此处略去。

讲了这么多,一点代码也没有,总该来道题吧!

于是模板题来了!(数竞党慎入)

P4781【模板】拉格朗日插值法

直接上代码吧:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2005;
const int MOD=998244353;
typedef long long ll;
int n,k;
ll x[maxn];
ll y[maxn];
inline ll ksm(ll x,int y){
	if(!y) return 1;
	if(y==1) return x%MOD;
	ll tmp=ksm(x,y/2);
	tmp=(tmp*tmp)%MOD;
	if(y&1) return (tmp*x)%MOD;
	else return tmp; 
}
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++) scanf("%lld%lld",&x[i],&y[i]);
	ll ans=0;
	for(int i=1;i<=n;i++){
		ll s1=y[i]%MOD; 
		ll s2=1;
		for(int j=1;j<=n;j++) if(i!=j){
			s1=(s1*(k-x[j]))%MOD;
			s1=(s1+MOD)%MOD;
			s2=(s2*(x[i]-x[j]))%MOD;
			s2=(s2+MOD)%MOD;
		}
		ans=(ans+(s1*ksm(s2,MOD-2))%MOD)%MOD;
		ans=(ans+MOD)%MOD;
	}
	printf("%lld
",ans);
	return 0;
}

六、多项式乘法的优化

我们先前讨论过多项式的点值表示法。

普通的多项式乘法是(O(n^2))的,但如果我们换成点值表示法呢?

现在我们有两个多项式(f(x))(g(x)),记它们的积为(r(x))

则对于同样的(a),它们分别有点值((a,y_f))((a,y_g))((a,y_r))

显然,(y_r=y_f*y_g)

所以如果我们对于每个参与乘法的多项式有(n)个点值的话,我们可以在(O(n))的时间内完成乘法运算!

于是,对于系数表示法的多项式的乘法运算,我们可以尝试用点值表示法优化。

过程如下:

1.将系数表达法的多项式改写为点值表示法的多项式(点值过程

2.用点值表示法计算多项式的乘法。

3.将点值表示法转化为系数表示法。(插值过程

下面,我们重点介绍完成这一过程的算法。

七、DFT,IDFT与FFT

DFT:离散傅里叶变换,用来完成点值过程。

IDFT:离散反傅里叶变换,用来完成插值过程。

FFT:DFT和IDFT的高效算法。

前置知识

1.复数

我们把形如(a+bi(a,bin R))的数称为复数,其中(i)为虚数单位,规定

[i^2=-1 ]

其中(a)被称为实部,(b)被称为虚部。

知道这玩意有啥用?(我还是个初中的蒟蒻

一会你就知道了。

我们大家都知道笛卡尔发明的万恶的平面直角坐标系。

对于复数,我们有一个类似的东西:复平面

u=3797762356,1963283957&fm=26&gp=0

复平面的横轴是实数轴,纵轴是虚数轴。

于是对于每一个复数,我们都有一个唯一对应的向量了。

我们可以用((r, heta))来表示一个虚数,其中(r)为虚数的长度,( heta)为该向量与(x)轴正半轴的夹角。

复数也是有它的四则运算的。

对于两个复数(z_1=a+bi)(z_2=c+di),它们的和 和 积为:

[z_1+z_2=(a+c)+(b+d)i\ z_1 imes z_2=(a+bi)(c+di)=(ac-bd)+(ad+bc)i ]

复数相加和向量加法一样,满足平行四边形法则

对于乘法,如果用坐标表示的话,我们有:

[(r_1, heta_1) imes(r_2, heta_2)=(r_1 imes r_2, heta_1+ heta_2) ]

即传说中的模长相乘,辐角相加

所以如果两个复数的长度都是1,那他们的乘法就知识单纯的角度相加了。

2.单位根

对于我们的点值过程,我们当然可以随便取几个值代入去算。

但显然,暴力计算(x,x^2,x^3...,x^n)当然是(O(n^2))的。

我们可不可以不计算这些呢?

我们当然希望这些数是(1,-1)这样的数,因为它们的若干次方是1。但明显,这不够。

傅里叶:这个圆上的每个点都可以。捕获

没错,这个圆是单位圆

我们可以把这个圆(n)注意:(n)是2的幂次)等分,从((1,0))开始,编号为(0)(n-1)。我们记编号为(k)的点为(w_n^k)

显然,((w_n^1)^k=w_n^k(k ot=0))(模长相乘,辐角相加)。

我们把(w_n^1)称为(n)次单位根,简单记为(w_n)

而这些(w_n^0,w_n^1,w_n^2,...,w_n^{n-1})有个极其重要的性质:它们的(n)次方等于1!

下面我们就要来证明这个性质:

对于(w_n^0),它恒等于1。

而对于大于0的正整数(k)而言,(w^k_n=(w^1_n)^k)

所以只要证明(w_n)(n)次方等于1即可。

由于我们是把单位圆(n)等分,我们很容易得到(注意这是单位圆):

[w_n=cos frac{2pi}{n}+isin frac{2pi}{n} ]

由欧拉公式

[e^{ix}=cos x+isin x ]

(x)(frac{2pi}{n})

[w_n=e^{frac{2pi i}{n}} ]

所以

[(w_n)^n=(e^{frac{2pi i}n{}})^n=e^{2pi i} ]

欧拉公式中的(x)(2pi)

[e^{2pi i}=cos 2pi +i sin 2pi =1 ]

所以

[(w_n)^n=1 ]

证毕。

单位根还有以下两个性质:

1.(w_{2n}^{2k}=w_n^k)

它们表示的复数(向量)是相同的,可以感性理解以下。

2.(w_n^{k}=-w_{n}^{k+frac{n}{2}})

它们表示的向量等大而且反向((frac{n}{2})表示二分之一个圆周)

上面两个性质可以结合欧拉公式给出证明,但我觉得证明了反而不是那么好理解了。

快速傅里叶变换(FFT)

有了单位根,我们就可以在DFT的过程中减少次方运算了。

但对于不是(2)的幂次的项,还是要我们暴力乘出来,总体的时间复杂度依然是(O(n^2))的。

这时,FFT闪亮登场!

第一步:离散傅里叶变换(DFT)

现在我们有一个(n)项的多项式(同样地,(n)是2的幂次,且这里(nge2)):

[f(x)=a_0+a_1x+a_2x^2+...+a_{n-1}x^{n-1} ]

我们现在根据奇偶性把这个多项式分为两半:

[f(x)=(a_0+a_2x^2+...+a_{n-2}x^{n-2})+(a_1x+a_3x^3+...+a_{n-1}x^{n-1})\ =(a_0+a_2x^2+...+a_{n-2}x^{n-2})+x(a_1+a_3x^2+...+a_{n-1}x^{n-2}) ]

我们再令:

[g(x)=a_0+a_2x+a_4x^2+...+a_{n-2}x^{frac{n}{2}-1}\ r(x)=a_1+a_3x+a_5x^2+...+a_{n-1}x^{frac{n}{2}-1} ]

(x^2)代入(g(x),r(x))

[g(x^2)=a_0+a_2x^2+a_4x^4+...+a_{n-2}x^{n-2}\ r(x^2)=a_1+a_3x^2+a_5x^4+...+a_{n-1}x^{n-2} ]

所以

[f(x)=g(x^2)+x imes r(x^2) ]

我们设(k<frac{n}{2}),代入(w_n^k)得:

[f(w_n^k)=g((w_n^k)^2)+w_n^k imes r((w_n^k)^2)\ =g(w_n^{2k})+w_n^k imes r(w_n^{2k})\= g(w_{frac{n}{2}}^k)+w_n^k imes r(w_{frac{n}{2}}^k) ]

我们再代入(w_n^{k+frac{n}{2}})

[f(w_n^{k+frac{n}{2}})=g((w_n^{k+frac{n}{2}})^2)+w_n^{k+frac{n}{2}} imes r((w_n^{k+frac{n}{2}})^2)\ =g(w_n^{2k+n})+w_n^{k+frac{n}{2}} imes r(w_n^{2k+n})\ =g(w_n^{2k}w_n^n)+w_n^{k+frac{n}{2}} imes r(w_n^{2k}w_n^n)\ =g(w_{frac{n}{2}}^k)-w_n^k imes r(w_{frac{n}{2}}^k) ]

以上两式常被称为蝴蝶操作

我们于是得到了一个结论:

如果我们知道(g(x))(r(x))(w_{frac{n}{2}}^0,w_{frac{n}{2}}^1,...,w_{frac{n}{2}}^{n-1})处的值,那么我们就可以在线性时间内求出(f(x))(w_n^0,w_n^1,...,w_n^{n-1})处的值。

我们再对(g(x))(r(x))进行相同的操作,于是我们就可以这么递归分治向下求解了。

注意:我们只能对长度为(2)的次幂的数列进行分治FFT,否则递归向下的话两边长度就不相等了。

一般对于这种情况,我们可以在第一次DFT之前把序列长度补成2的次幂。对于新补的高次项,我们令他们的系数为0。

这样,算法的时间复杂度就是(O(nlog n))了。

但是,我相信大家都知道,递归过程是很耗内存的。

我们能不能不递归就进行FFT呢?

当然可以!

我们完全可以在原序列里把这些系数拆分了,然后在“倍增”地合并。

现在的关键问题就是我们如何拆分这些系数了。

这里我盗张图

捕获2

有啥规律呢?

对于原序列中的系数(a_i),令(i)做二进制位翻转操作后的结果为(rev(i))(比如说:在长度为8的情况下,1就是001,翻转之后就是100,即4),那么(a_i)最后的位置就是(rev(i))

第二步:离散反傅里叶变换(IDFT)

IDFT的过程的作用我们先前说过了,就是要完成插值过程。

我们把单位根代入,就得到下面的线性方程组的等效矩阵:

[egin{bmatrix} 1& 1 &1 &cdots& 1\ 1& w_n^1& w_n^2&cdots &w_n^n\ 1& w_n^2& w_n^4&cdots &w_n^{2n}\ vdots& vdots &vdots &ddots &vdots \ 1& w_n^{n-1}&w_n^{2n-2}&cdots & w_n^{(n-1)^2} end{bmatrix} egin{bmatrix} a_0\ a_1\ a_2\ vdots\ a_{n-1} end{bmatrix} = egin{bmatrix} y_0\ y_1\ y_2\ vdots\ y_{n-1} end{bmatrix} ]

我们仍然记为(XA=Y)

相当于我们现在知道了(X,Y)去求(A)了。

我们前面在探究多项式插值的时候,我们已经说明了多项式插值的存在性与唯一性(忘了可以重新看一眼)。

现在,(A=X^{-1}Y),我们前面已经说明(X)存在逆矩阵,于是问题的关键就是求这个逆矩阵了。

我们知道,(X)是范德蒙矩阵,它的行列式有它的特殊计算方式,而它的逆矩阵也有他独特的性质,就是每一项取倒数,再除以(n)(为什么是这样,我不会证

我们在先前探讨单位根的时候,我们知道:

[w_n=e^{frac{2pi i}{n}} ]

我们现在取倒数,即-1次方:

[w_n^{-1}=e^{frac{-2pi i}{n}} ]

于是我们只要把(pi)取成(-3.1415926...),然后其他过程和DFT是一样的!

所以,我们只需要一个函数,就可以完成DFT与IDFT两个操作了。

好了,放上一道模板题:P3803 【模板】多项式乘法(FFT)

Code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
const double Pi=acos(-1.0);
struct Complex{
	double x,y;
	Complex(double a=0,double b=0){
		x=a; y=b;
	}
	Complex operator +(const Complex a)const{
		return Complex(x+a.x,y+a.y);
	} 
	Complex operator *(const Complex a)const{
		return Complex(x*a.x-y*a.y,x*a.y+y*a.x);
	}
	Complex operator -(const Complex a)const{
		return Complex(x-a.x,y-a.y);
	}
}a[maxn<<1],b[maxn<<1];
int n,m;
int len;
int r[maxn<<1];
inline int read(){
	char ch=getchar(); int sum=0; int f=1;
	while(!isdigit(ch)) f=ch=='-'?-1:1,ch=getchar();
	while(isdigit(ch)) sum=sum*10+ch-'0',ch=getchar();
	return sum*f; 
}
inline void FFT(Complex *a,int len,int on){
	for(int i=0;i<len;i++)
		if(i<r[i]) swap(a[i],a[r[i]]);
	for(int i=2;i<=len;i<<=1){//一次合并的长度
		Complex wn(double(cos(2*Pi/i)),double(sin(on*2*Pi/i)));//当前单位根
		for(int j=0;j<len;j+=i){//对每一块分别计算
			Complex w(1,0);
			for(int k=j;k<j+i/2;k++){//蝴蝶操作,计算当前多项式的点值
				Complex u=a[k];
				Complex t=w*a[k+i/2];
				a[k]=u+t;
				a[k+i/2]=u-t;
				w=wn*w;
			}
		}
	}
	if(on==-1) for(int i=0;i<len;i++) a[i].x/=len; 
}
int main(){
	n=read(); m=read();
	for(int i=0;i<=n;i++) a[i].x=read();
	for(int i=0;i<=m;i++) b[i].x=read();
	len=1; int cnt=0;
	while(len<=n+m) len<<=1,cnt++;//补成2^k长度
	for(int i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(cnt-1));//找到对应位置
	FFT(a,len,1);//DFT
	FFT(b,len,1);
	for(int i=0;i<len;i++) a[i]=a[i]*b[i];//多项式乘法(用点值计算)
	FFT(a,len,-1);//IDFT
	for(int i=0;i<=n+m;i++) printf("%d ",int(a[i].x+0.5));//注意加0.5,防止被卡精度
	printf("
");
	return 0;
} 

我们这是“多项式入门”,也就入门到这了!

多项式还有很多内容,包括:

  • 快速数论变换(NTT)
  • 快速沃尔什变换(FWT)
  • 多项式求逆
  • 多项式开方
  • 多项式除法
  • 多项式取模
  • 多项式的对数函数与指数函数
  • 多项式的三角函数与反三角函数
  • 多项式牛顿迭代
  • 多项式快速插值|多点求值

这些已经超过我的能力范围(我毕竟还只是一个初中的蒟蒻OIer)。

如果以后有机会的话,我会更新一个叫做多项式进阶的博客的!

如有不足之处请指正,谢谢!

参考资料:

1.苏科版七年级上册《数学》教科书

2.2002年国家集训队论文 张家琳《多项式乘法》

3.2016年国家集训队论文 毛啸 《再探快速傅里叶变换》

3.华东师范大学出版社《奥数教程》高中第三分册

4.百度百科 范德蒙行列式

5.OI wiki 快速傅里叶变换

原文地址:https://www.cnblogs.com/ybwowen/p/11153817.html