zoukankan      html  css  js  c++  java
  • 基础多项式的自闭学习历程

    写在前面

    1. 看洛谷网课学的
    2. 规定字母的加重字体为一个数列,如(a)的加重字体为(mathbf a)(mathbf a)即为一个数列
    3. 博猪现在的水平,不足以继续往下学习了,所以……咕咕咕
    4. 我一定会更新哒!

    多项式

    多项式的定义

    一个环(R)上的关于(x)的多项式可以写作

    [A(x)=sumlimits_{i=0}^{n}a_ix^i ]

    其中(a_iin R),被称为这个多项式的系数。(x)是一个不在环上的元素,只起一个占位的作用,并没有实际的意义,被称为这个多项式的自由元。

    多项式的次数被定义为其最高非零次项的次数,记为(deg A(x))

    可以认为(FFT)是在复数域上的操作,(NTT)是在有限域上的操作

    多项式运算

    加减法

    加减法比较好理解.

    (A(x),B(x))是次数不超过(n)的多项式。

    那么加法和减法运算被定义为:

    [A(x)pm B(x)=sum_{i=0}^{n}(a_ipm b_i)x^i ]

    显然可以在(O(n))时间内计算这两个多项式的和或差。

    乘法

    乘法可能不那么好理解,所以我们要先接触一个概念:卷积

    卷积

    (mathbf{a,b})是两个数列,那么这两个数列的卷积(mathbf c)的定义为

    [c_k=sumlimits_{i+j=k}a_ib_j ]

    (eg.)

    • 假设现在我们有(mathbf{a,b})两个数列,数列中的值分别为(a_0,a_1,a_2)(b_0,b_1,b_2),那么这两个数列的卷积(mathbf c)中的元素就是(c_0=a_0b_0,c_1=a_0b_1+a_1b_0,c_2=a_0b_2+a_1b_1+a_2b_0),也就是说原数列元素的下标之和等于新的下标

    多项式乘法

    两个多项式的乘积被定义为:

    [A(x)B(x)=sumlimits_{i=0}^{n}sumlimits_{j=0}^{n}a_ib_jx^{i+j}=sumlimits_{i=0}^{2n}c_kx^k ]

    其中(mathbf c)(mathbf a)(mathbf b)的卷积。朴素地按定义计算多项式乘法的时间复杂度是(O(n^2))

    (ps:)两个多项式的乘法不一定要同次

    多项式的点值表示

    给定一个不超过(n)次的多项式(A(x))以及(n+1)个不同的点(x_0,x_1,x_2,…,x_n),令(y_i=A(x_i))

    则这(n+1)((x_i,y_i))唯一的确定了这个多项式(A(x))。这些点((x_i,y_i))称作这个多项式的点值表示。(其实也可以用向量表示)

    假设给出了(n+1)个点((x_0,y_0),…(x_n,y_n))(x_i)互不相同),要求找出一个过所有点的多项式函数(A(x)),则可以用高斯消元法求出,但是高斯消元时间复杂度比较高而且有精度误差,这个时候我们就可以考虑用拉格朗日插值

    拉格朗日插值公式

    [A(x)=sumlimits_{i=0}^{n-1}y_ifrac{prodlimits_{j e i}(x-x_j)}{prodlimits_{j e i}(x_i-x_j)} ]

    利用拉格朗日插值公式可以在给定(n)个点值表示法的情况下(O(n^2))时间内计算出原二项式在某个位置的值


    如果给出(A(x))(B(x))分别在(x_0,x_1,…,x_n)下的点值,则可以在(O(n))时间内得到 (A(x)pm B(x))(A(x)B(x))在同一组位置处的点值。

    前置知识

    复数

    咕咕咕(我还不知道怎么简洁地叙述

    单位根

    满足(x^n-1=0)(x)被称作(n)次单位根。

    (omega)(n)次单位根。如果恰好(omega^0,omega^1,…omega^{n-1})生成了所有的(n)次单位根(即两两不同),则称(omega)为本原单位根。这等价于(n)是最小的使得(omega^n-1=0)的正整数。我们(omega_n)来表示一个(n)次本原单位根。

    在复数域(C)上,(omega_n=exp(frac{2pi i}{n})=cosfrac{2pi}{n}+isinfrac{2pi}{n})是一个本原单位根。下文首先考虑负数域(C)上的多项式。

    在有限域(即模素数的情况)中,本原单位根与数论中的原根有关。

    离散傅里叶变换(DFT)

    (mathbf a)是长度为(n)的数列,对(0leq k < n),令

    [b_k=sumlimits_{i=0}^{n-1}a_icdot omega_n^{ ki} ]

    则称(mathbf b)(mathbf a)的离散傅里叶变换(( ext{DFT})),记作(mathbf b=mathcal{F}(mathbf a))(mathcal{F})就表示离散傅里叶变换。

    容易看出,令(A(x)=sum a_ix^i),则(b_k)就是(A(x))(omega_n^{ k})处的点值。因此计算(mathbf a)( ext{DFT})与计算(A(x))(omega_n^{ 0},omega_n^{ 1},…,omega_{n}^{ n - 1})处的点值表示是等价的。

    离散傅里叶逆变换(IDFT)

    ({ ext{IDFT}})是啥?能吃吗?

    对于长度(n)为的序列(mathbf{a,b}),回忆( ext{DFT})的定义:

    [b_k=sumlimits_{i=0}^{n-1}a_icdot omega_n^{ ki}(0leq k < n) ]

    ( ext{DFT})的逆变换( ext{IDFT})如下:

    [a_k=frac 1nsumlimits_{i=0}^{n-1}b_icdot omega_n^{ -ki}(0leq k < n) ]

    ( ext{IDFT})( ext{DFT})的逆变换,也就意味着已知多项式在单位根处的点值,( ext{IDFT})能够求出多项式的各项系数。在这种意义上,这个过程也可以看作插值。

    快速傅里叶变换(FFT)

    引子—循环卷积

    对于两个长度为(n)的序列(mathbf{a,b}),定义

    [c_k=sumlimits_{(i+j) ext{mod} n=k}a_ib_j ]

    则称(mathbf c)(mathbf a)(mathbf b)的循环卷积,记为(mathbf{c=a*b})

    关于循环卷积与( ext{DFT}),我们有如下定理:

    (mathcal{F}(mathbf{a*b})=mathcal{F}(mathbf a)cdotmathcal{F}(mathbf b))

    其中(cdot)表示逐点乘积

    白话就是(mathbf a)(mathbf b)的循环卷积的离散傅里叶变换等于(mathbf a)的离散傅里叶变换逐点乘上(mathbf b)的离散傅里叶变换(显然很啰嗦,还是看式子⑧)

    ??

    上面的离散傅里叶变换(( ext{DFT}))计算卷积的复杂度是(O(n^2))的,快速傅里叶变换是快速计算 ( ext{DFT})的方法,可以优化到(O(n log n))

    然后

    不会 没了

  • 相关阅读:
    PHP基础知识(十一)
    PHP基础知识(十)
    PHP基础知识(九)
    PHP中禁用cookie后session的实现
    PHP基础知识(八)
    将博客搬至CSDN
    如何为预先数据库创建自定义SQL Server复制
    数据库同步工具
    如何终止与MySQL数据库的某些连接
    从Oracle到SQL Server和从SQL Server到Oracle的迁移指南
  • 原文地址:https://www.cnblogs.com/loceaner/p/13200267.html
Copyright © 2011-2022 走看看