部分内容引自command_block的博客OI Wiki多项式求逆部分Great_Influence的博客

 



多项式基础知识

多项式的表示法

系数表示法

$$f(x)=\sum\limits_{i=0}^na_i*x^i$$

点值表示法

引理:$n+1$个不同的点可以唯一确定一个最高为$n$次的多项式

给出$n+1$维二元向量组$(\vec{x},\vec{y})$,满足$f(x_i)=y_i(\forall i,j\ s.t.\ x_i\ne x_j)$,确定一个多项式的形式

求值和插值

多项式求值:将系数表示转化为点值表示

多项式插值:将点值表示转化为系数表示

多项式插值及上述引理的解释:

多项式插值的本质是范德蒙矩阵求逆

$$\begin{bmatrix}1&x_1&x_1^2&\cdots&x_1^n\\1&x_2&x_2^2&\cdots&x_2^n\\\vdots&\vdots&\vdots&\ddots&\vdots\\1&x_{n+1}&x^2_{n+1}&\cdots&x^n_{n+1}\end{bmatrix}\begin{bmatrix}a_0\\a_1\\\vdots\\a_n\end{bmatrix}=\begin{bmatrix}y_1\\y_2\\\vdots\\y_{n+1}\end{bmatrix}$$

可以证明若$x_i$各不相同则范德蒙矩阵一定可逆,则系数向量$\vec{a}$有唯一解

多项式加减法

系数表示法

$$A(x)±B(x)=\sum\limits_{i=0}^n(a_i±b_i)*x^i$$

点值表示法

$$(\vec{x},\vec{y_a})±(\vec{x},\vec{y_b})=(\vec{x},\vec{y_a}±\vec{y_b})$$

多项式乘法

系数表示法

$$A(x)×B(x)=\sum\limits_{i=0}^n\sum\limits_{j=0}^na_i×b_j×x^{i+j}=\sum\limits_{i=0}^{2n}\sum\limits_{j=0}^{min(i,n)}a_j×b_{i-j}×x^i$$

点值表示法(向量$\vec{x},\vec{y_a},\vec{y_b}$应为$2n+1$维以确定$2n$次多项式)

$$(\vec{x},\vec{y_a})*(\vec{x},\vec{y_b})=(\vec{x},\vec{y}),y_k=y_{a_k}y_{b_k}$$

卷积运算

$$c_k=\sum\limits_{i⊕j=k}a_ib_j$$

其中⊕为某种运算

点值表示下的多项式乘法即为加法卷积

拉格朗日插值法

给定$n+1$个互不相同的点,确定$n$次多项式$f(x)$, 第$i$个点的坐标为$(x_i,y_i)$,我们需要找到该多项式在$k$点的取值,根据拉格朗日插值法有

$$f(k)=\sum\limits_{i=0}^ny_i\prod\limits_{i\ne j}\frac{k-x[j]}{x[i]-x[j]}$$

复杂度为$O(n^2)$

快速傅里叶变换$(FFT)$

基本思想:将系数表达转化为点值表达,利用点值表达相乘计算多项式乘法,再将点值表达相乘的结果转化为系数表达

将系数表达转化为点值表达$(DFT)$:

若$n$不是$2$的整数次幂,则补若干系数为$0$的项使$n$成为$2$的整数次幂

对$n$次多项式$f(x)=\sum\limits_{i=0}^na_ix^i$,按$x$次数的奇偶性划分可得$f(x)=\sum\limits_{i=0}^{2i\le n}a_{2i}x^{2i}+\sum\limits_{i=0}^{2i+1\le n}a_{2i+1}x^{2i+1}$

令多项式

$f_1(x)=\sum\limits_{i=0}^{2i\le n}a_{2i}x^{i},f_2(x)=\sum\limits_{i=0}^{2i+1\le n}a_{2i+1}x^{i}$

则$f(x)=f_1(x^2)+xf_2(x^2)$

分别代入$w_{n+1}^k,w_{n+1}^{k+\frac{n+1}{2}}$可得

$$f(w_{n+1}^k)=f_1(w_{\frac{n+1}{2}}^k)+w_{n+1}^kf_2(w_{\frac{n+1}{2}}^k)\qquad(1)$$

$$f(w_{n+1}^{k+\frac{n+1}{2}})=f_1(w_{\frac{n+1}{2}}^k)-w_{n+1}^kf_2(w_{\frac{n+1}{2}}^k)\qquad(2)$$

所以如果我们知道两个多项式$f_1(x)$和$f_2(x)$分别在$w_{\frac{n+1}{2}}^0...w_{\frac{n+1}{2}}^{\frac{n+1}{2}-1}$的点值表示

利用式$(1)$可求$f(x)$在$w_{n+1}^0...w_{n+1}^{\frac{n+1}{2}-1}$的点值表示,利用式$(2)$可求$f(x)$在$w_{n+1}^{\frac{n+1}{2}}...w_{n+1}^{n}$的点值表示,时间复杂度为$O(n)$

而对于$f_1(x),f_2(x)$也满足同样的性质,递归求解即可,时间复杂度$O(nlogn)$

单位根求解:$w_n^k=cos\frac{2\pi k}{n}+i*sin\frac{2\pi k}{n}$

将点值表达转化为系数表达$(IDFT)$

设$g=DFT(f)$即$g(k)=\sum\limits_{i=0}^n(w_{n+1}^k)^if(i)$

则有$f=IDFT(g)$即$f(k)=\frac{1}{n}\sum\limits_{i=0}^n(w_{n+1}^{-k})^ig(i)$

挂一手代码,朴素递归写法(多项式乘法)

 

#include<iostream>
#include<cstdio>
#include<cmath>
#define PAI acos(-1)
using namespace std;
const int maxn=4e6+10;
struct complex{
    double a,b;
}f[maxn],g[maxn],mul[maxn];
int n,m,N;
complex operator *(const complex &x,const complex &y)
{
    return (complex){x.a*y.a-x.b*y.b,x.a*y.b+x.b*y.a};
}
complex operator +(const complex &x,const complex &y)
{
    return (complex){x.a+y.a,x.b+y.b};
}
complex operator -(const complex &x,const complex &y)
{
    return (complex){x.a-y.a,x.b-y.b};
}
int up(int x)
{
    int ret=1;
    for(;ret<x;ret*=2);
    return ret;
}
complex makew(int len,int k)
{
    return (complex){cos(2*PAI*k/len),sin(2*PAI*k/len)};
}
void fft(int ty,int len,complex *a)
{
    if(len==1)
        return;
    complex f1[len/2],f2[len/2];
    for(int i=0;2*i<len;i++)
        f1[i]=a[2*i];
    for(int i=0;2*i+1<len;i++)
        f2[i]=a[2*i+1];
    fft(ty,len/2,f1),fft(ty,len/2,f2);
    for(int i=0;i<len/2;i++)
    {
        complex w=makew(len,ty*i);
        a[i]=f1[i]+w*f2[i];
        a[i+len/2]=f1[i]-w*f2[i];
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    N=up(n+m+1);
    for(int i=0;i<=n;i++)
        scanf("%lf",&f[i].a);
    for(int i=0;i<=m;i++)
        scanf("%lf",&g[i].a);
    fft(1,N,f),fft(1,N,g);
    for(int i=0;i<N;i++)
        mul[i]=f[i]*g[i];
    fft(-1,N,mul);
    for(int i=0;i<n+m+1;i++)
        printf("%d ",(int)(mul[i].a/N+0.5));
    printf("\n");
    return 0;
}
View Code

相关文章:

  • 2021-12-27
  • 2021-07-04
  • 2021-09-27
  • 2021-05-27
  • 2021-10-08
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-01-02
  • 2021-08-26
  • 2021-06-05
  • 2022-02-06
  • 2021-11-30
  • 2021-12-05
  • 2021-10-03
相关资源
相似解决方案