分治法求解多项式乘法

news2024/9/25 3:26:00

目录

  • 多项式乘法问题
  • 暴力求解
  • 背景展开
    • 1. 系数表示值计算复杂度
    • 2. 点值法表示多项式
    • 3. 点值表示值计算复杂度
    • 4. 系数法和点值法比较
    • 5. 系数法和点值法的转换
  • 快速傅里叶变换 FFT
    • 1. 多项式乘法的分治
    • 2. 取值的直觉
    • 3. 离散傅里叶 DFT 和单位根
    • FFT

多项式乘法问题

多项式乘法是将两个或多个多项式相乘,得到一个新的多项式。

一个多项式通常写成如下的形式(系数表示): P ( x ) = a n x n + a n − 1 x n − 1 + … + a 1 x + a 0 P(x) = a_nx^n + a_{n-1}x^{n-1} + \ldots + a_1x + a_0 P(x)=anxn+an1xn1++a1x+a0其中 a i a_{i} ai是多项式的系数, x x x 是变量, n n n 是多项式的次数。

假设我们有两个多项式: P ( x ) = a n x n + a n − 1 x n − 1 + … + a 1 x + a 0 Q ( x ) = b m x m + b m − 1 x m − 1 + … + b 1 x + b 0 P(x) = a_nx^n + a_{n-1}x^{n-1} + \ldots + a_1x + a_0 \\ Q(x) = b_mx^m + b_{m-1}x^{m-1} + \ldots + b_1x + b_0 P(x)=anxn+an1xn1++a1x+a0Q(x)=bmxm+bm1xm1++b1x+b0它们的乘积 R ( x ) = P ( x ) ⋅ Q ( x ) R(x)=P(x)⋅Q(x) R(x)=P(x)Q(x) 可以通过将 P ( x ) P(x) P(x) 中的每一项与 Q ( x ) Q(x) Q(x) 中的每一项相乘,然后将结果合并得到: R ( x ) = ∑ i = 0 n ∑ j = 0 m a i b j x i + j R(x) = \sum_{i=0}^{n} \sum_{j=0}^{m} a_ib_jx^{i+j} R(x)=i=0nj=0maibjxi+j其中, i i i j j j 分别表示 P ( x ) P(x) P(x) Q ( x ) Q(x) Q(x) 中各项的指数, a i a_{i} ai b j b_{j} bj 分别是对应的系数。

暴力求解

对于规模相当的两个多项式相乘,对于 P ( x ) P(x) P(x) 的每个项,都要与 Q ( x ) Q(x) Q(x) 相乘,并进行结果的累加。这个过程的算法复杂度很容易得知为 O ( n 2 ) O(n^{2}) O(n2)

#include <iostream>
#include <vector>

using namespace std;

// 结构体表示多项式的一项
struct Term {
    int coefficient;
    int exponent;
};

// 函数实现多项式相乘
vector<Term> multiplyPolynomials(vector<Term>& poly1, vector<Term>& poly2) {
    vector<Term> result;

    for (int i = 0; i < poly1.size(); ++i) {
        for (int j = 0; j < poly2.size(); ++j) {
            int newCoefficient = poly1[i].coefficient * poly2[j].coefficient;
            int newExponent = poly1[i].exponent + poly2[j].exponent;

            bool termExists = false;
            for (int k = 0; k < result.size(); ++k) {
                if (result[k].exponent == newExponent) {
                    result[k].coefficient += newCoefficient;
                    termExists = true;
                    break;
                }
            }

            if (!termExists) {
                Term newTerm = {newCoefficient, newExponent};
                result.push_back(newTerm);
            }
        }
    }

    return result;
}

int main() {
    vector<Term> poly1 = {{2, 2}, {3, 1}, {1, 0}};
    vector<Term> poly2 = {{4, 1}, {1, 0}};

    vector<Term> result = multiplyPolynomials(poly1, poly2);

    cout << "Result: ";
    for (int i = 0; i < result.size(); ++i) {
        cout << result[i].coefficient << "x^" << result[i].exponent;
        if (i < result.size() - 1) {
            cout << " + ";
        }
    }
    cout << endl;

    return 0;
}


背景展开

1. 系数表示值计算复杂度

对于给定多项式和值 x x x : A ( x ) = a n − 1 x n − 1 + … + a 1 x + a 0 B ( x ) = b n − 1 x n − 1 + … + b 1 x + b 0 A(x) = a_{n-1}x^{n-1} + \ldots + a_1x + a_0 \\ \\ B(x) = b_{n-1}x^{n-1} + \ldots + b_1x + b_0 A(x)=an1xn1++a1x+a0B(x)=bn1xn1++b1x+b0- 加法计算复杂度 O ( n ) O(n) O(n)
A ( x ) + B ( x ) = ( a 0 + b 0 ) + ( a 1 + b 1 ) x + . . . ( a n − 1 + b n − 1 ) x n − 1 A(x)+B(x)=(a_{0}+b_{0})+(a_{1}+b_{1})x+...(a_{n-1}+b_{n-1})x^{n-1} A(x)+B(x)=(a0+b0)+(a1+b1)x+...(an1+bn1)xn1 - 乘法计算复杂度 采用Horner (霍氏法则) O ( n ) O(n) O(n) A ( x ) = a 0 + ( x ( a 1 + x ( a 2 + . . . + x ( a n − 2 + x ( a n − 1 ) ) . . . ) ) A(x) = a_0 + (x(a_1 + x(a_2 + ... + x(a_{n−2} + x(a_{n−1}))...)) A(x)=a0+(x(a1+x(a2+...+x(an2+x(an1))...))


2. 点值法表示多项式

在这里插入图片描述
当我们用点值法表示多项式时,我们通常是指将多项式表示为一组在特定点 x x x 处的函数值。

假设我们有一个多项式 P ( x ) P(x) P(x) ,我们可以在一些特定的点 x 1 , x 2 , … , x n x_1,x_2,…,x_n x1,x2,,xn 处计算它的值 P ( x 1 ) , P ( x 2 ) , … , P ( x n ) P(x_1),P(x_2),…,P(x_n) P(x1),P(x2),,P(xn) 。这些点和相应的函数值可以表示为: ( x 1 , P ( x 1 ) ) ( x 2 , P ( x 2 ) ) . . . . . . ( x n , P ( x n ) ) (x_1, P(x_1)) (x_2, P(x_2)) ...... (x_n, P(x_n)) (x1,P(x1))(x2,P(x2))......(xn,P(xn))一个 n n n 次的复系数单变量多项式恰好有 n n n 个复根。


3. 点值表示值计算复杂度

对于给定多项式点值列 x x x : A ( x ) : ( x 0 , y 0 ) , . . . , ( x n − 1 , y n − 1 ) B ( x ) : ( x 0 , z 0 ) , . . . , ( x n − 1 , z n − 1 ) A(x) : (x_0,y_0),...,(x_{n-1},y_{n-1}) \\ \\ B(x) : (x_0,z_0),...,(x_{n-1},z_{n-1}) A(x):(x0,y0),...,(xn1,yn1)B(x):(x0,z0),...,(xn1,zn1)- 加法计算复杂度 O ( n ) O(n) O(n)
A ( x ) + B ( x ) : ( x 0 , y 0 + z 0 ) , . . . , ( x n − 1 , y n − 1 + z n − 1 ) A(x)+B(x):(x_{0},y_{0}+z_0),...,(x_{n-1},y_{n-1}+z_{n-1}) A(x)+B(x):(x0,y0+z0),...,(xn1,yn1+zn1) - 乘法计算复杂度 O ( n ) O(n) O(n) 但是需要用 2 n 2n 2n 个点表示 A ( x ) A(x) A(x) B ( x ) B(x) B(x) A ( x ) × B ( x ) : ( x 0 , y 0 × z 0 ) , . . . , ( x 2 n − 1 , y 2 n − 1 × z 2 n − 1 ) A(x) \times B(x):(x_0,y_0 \times z_0),...,(x_{2n-1},y_{2n-1} \times z_{2n-1}) A(x)×B(x):(x0,y0×z0),...,(x2n1,y2n1×z2n1)- 计算给定点 s s s ,使用拉格朗日公式 O ( n 2 ) O(n^2) O(n2): A ( s ) = ∑ k = 0 n − 1 y k ∏ j ≠ k ( s − x j ) ∏ j ≠ k ( x k − x j ) A(s)=\sum_{k=0}^{n-1}y_k\frac{\prod _{j\ne k}(s-x_j)}{\prod _{j\ne k}(x_k-x_j)} A(s)=k=0n1ykj=k(xkxj)j=k(sxj)


4. 系数法和点值法比较

表示方法多项式相乘多项式算值
系数法 O ( n 2 ) O(n^2) O(n2) O ( n ) O(n) O(n)
点值法 O ( n ) O(n) O(n) O ( n 2 ) O(n^2) O(n2)

如果能够同时利用 系数法的算值点值法的相乘 的低复杂度计算。那么对于整个多项式相乘就有了一个复杂度比较低的解决方式。其中的关键就是找到两者之间的沟通桥梁


5. 系数法和点值法的转换

在这里插入图片描述

系数法 → \rightarrow 点值法(通过矩阵向量乘法或 n n n 次霍氏乘法) O ( n 2 ) O(n^2) O(n2)

给定多项式 a ( x ) = a 0 + a 1 x + … + a n − 1 x n − 1 a (x) = a_0 + a_1x +…+ a_{n-1} x_{n - 1} a(x)=a0+a1x++an1xn1,在 n n n 个不同的点处求值 x 0 , … , x n − 1 x_0,…, x_{n-1} x0,,xn1: [ y 0 y 1 y 2 ⋮ y n − 1 ] = [ 1 x 0 x 0 2 … x 0 n − 1 1 x 1 x 1 2 … x 1 n − 1 1 x 2 x 2 2 … x 2 n − 1 ⋮ ⋮ ⋮ ⋱ ⋮ 1 x n − 1 x n − 1 2 … x n − 1 n − 1 ] [ a 0 a 1 a 2 ⋮ a n − 1 ] \begin{bmatrix}y_0\\y_1\\y_2\\\vdots \\y_{n-1}\end{bmatrix} = \begin{bmatrix} 1& x_0& x_0^2 & \dots &x_0^{n-1} \\ 1& x_1& x_1^2 & \dots & x_1^{n-1}\\ 1& x_2& x_2^2 & \dots & x_2^{n-1}\\ \vdots & \vdots & \vdots & \ddots & \vdots\\ 1& x_{n-1} & x_{n-1}^2 & \dots & x_{n-1}^{n-1} \end{bmatrix}\begin{bmatrix}a_0\\a_1\\a_2\\\vdots\\a_{n-1}\end{bmatrix} y0y1y2yn1 = 1111x0x1x2xn1x02x12x22xn12x0n1x1n1x2n1xn1n1 a0a1a2an1

点值法 → \rightarrow 系数法 (高斯消元 O ( n 3 ) O(n^3) O(n3) / 快速矩阵 O ( n 2.38 ) O(n^{2.38}) O(n2.38)):

给定n个不同的点 x 0 , … , x n − 1 x_0,…, x_{n-1} x0,,xn1和值 y 0 , … , y n − 1 y_0,…, y_{n - 1} y0,,yn1,求唯一多项式 A ( x ) = a 0 + a 1 x + … + a n − 1 x n − 1 A(x) = a_0 + a_1x +…+ a_{n-1} x_{n-1} A(x)=a0+a1x++an1xn1: [ a 0 a 1 a 2 ⋮ a n − 1 ] = [ 1 x 0 x 0 2 … x 0 n − 1 1 x 1 x 1 2 … x 1 n − 1 1 x 2 x 2 2 … x 2 n − 1 ⋮ ⋮ ⋮ ⋱ ⋮ 1 x n − 1 x n − 1 2 … x n − 1 n − 1 ] − 1 [ y 0 y 1 y 2 ⋮ y n − 1 ] \begin{bmatrix}a_0\\a_1\\a_2\\\vdots\\a_{n-1}\end{bmatrix} = \begin{bmatrix} 1& x_0& x_0^2 & \dots &x_0^{n-1} \\ 1& x_1& x_1^2 & \dots & x_1^{n-1}\\ 1& x_2& x_2^2 & \dots & x_2^{n-1}\\ \vdots & \vdots & \vdots & \ddots & \vdots\\ 1& x_{n-1} & x_{n-1}^2 & \dots & x_{n-1}^{n-1} \end{bmatrix}^{-1}\begin{bmatrix}y_0\\y_1\\y_2\\\vdots \\y_{n-1}\end{bmatrix} a0a1a2an1 = 1111x0x1x2xn1x02x12x22xn12x0n1x1n1x2n1xn1n1 1 y0y1y2yn1 其中等式右侧有关 x i x_i xi 的矩阵为范德蒙矩阵,当 x i x_i xi 不同时可逆。

通过直接线性代数的计算,并不能在低于 O ( n 2 ) O(n^2) O(n2) 的复杂度下完成两种表示方式的相互转换,甚至会增加额外的计算代价。这是难以接受的,因此我们需要寻找一种能够高效完成两种表示方式转换的算法,并且复杂度最好能够控制在 O ( n 2 ) O(n^2) O(n2) 以内。


快速傅里叶变换 FFT

在这里插入图片描述
可以使用快速傅里叶变换(FFT)来实现系数表示和点值表示的转换。FFT 可以在 O ( n l o g ⁡ n ) O(nlog⁡n) O(nlogn) 的时间内将多项式从系数形式转换为点值形式,以及从点值形式转换回系数形式。

1. 多项式乘法的分治

给定多项式如下: A ( x ) = a 0 + a 1 x + a 2 x 2 + a 3 x 3 + a 4 x 4 + a 5 x 5 + a 6 x 6 + a 7 x 7 A(x)=a_0+a_1x+a_2x^2+a_3x^3+a_4x^4+a_5x^5+a_6x^6+a_7x^7 A(x)=a0+a1x+a2x2+a3x3+a4x4+a5x5+a6x6+a7x7可以有如下两种分治测略:

拆分成低次和高次: A l o w ( x ) = a 0 + a 1 x + a 2 x 2 + a 3 x 3 A h i g h ( x ) = a 4 + a 5 x + a 6 x 2 + a 7 x 3 A_{low}(x)=a_0+a_1x+a_2x^2+a_3x^3 \\ A_{high}(x)=a_4+a_5x+a_6x^2+a_7x^3 Alow(x)=a0+a1x+a2x2+a3x3Ahigh(x)=a4+a5x+a6x2+a7x3合并 A ( x ) = A l o w ( x ) + x 4 A h i g h ( x ) A(x)=A_{low}(x)+x^4A_{high}(x) A(x)=Alow(x)+x4Ahigh(x)

拆分成奇偶次: A e v e n ( x ) = a 0 + a 2 x + a 4 x 2 + a 6 x 3 A o d d ( x ) = a 1 + a 3 x + a 5 x 2 + a 7 x 3 A_{even}(x)=a_0+a_2x+a_4x^2+a_6x^3 \\ A_{odd}(x)=a_1+a_3x+a_5x^2+a_7x^3 Aeven(x)=a0+a2x+a4x2+a6x3Aodd(x)=a1+a3x+a5x2+a7x3合并 A ( x ) = A e v e n ( x 2 ) + x A o d d ( x 2 ) A(x)=A_{even}(x^2)+xA_{odd}(x^2) A(x)=Aeven(x2)+xAodd(x2)


2. 取值的直觉

给定多项式 A ( x ) = a 0 + a 1 x + … + a n − 1 x n − 1 A (x) = a_0 + a_1x +…+ a_{n-1} x_{n - 1} A(x)=a0+a1x++an1xn1,在 n n n 个不同的点处求值 x 0 , … , x n − 1 x_0,…, x_{n-1} x0,,xn1

关于 x i x_i xi 的取值怎么取,一般性的直觉会选 0 , ± 1 , ± 2... 0,\pm 1,\pm 2... 0,±1,±2...。这是没问题的,直觉告诉我们选择对称的不同数值可以减少计算量。下面我们来验证这一直觉是否合理:

假如使用奇偶拆分法拆分 A ( x ) = a 0 + a 1 x + a 2 x 2 + a 3 x 3 + a 4 x 4 + a 5 x 5 + a 6 x 6 + a 7 x 7 A(x)=a_0+a_1x+a_2x^2+a_3x^3+a_4x^4+a_5x^5+a_6x^6+a_7x^7 A(x)=a0+a1x+a2x2+a3x3+a4x4+a5x5+a6x6+a7x7
A e v e n ( x ) = a 0 + a 2 x + a 4 x 2 + a 6 x 3 A o d d ( x ) = a 1 + a 3 x + a 5 x 2 + a 7 x 3 A_{even}(x)=a_0+a_2x+a_4x^2+a_6x^3 \\ A_{odd}(x)=a_1+a_3x+a_5x^2+a_7x^3 Aeven(x)=a0+a2x+a4x2+a6x3Aodd(x)=a1+a3x+a5x2+a7x3 A ( x ) = A e v e n ( x 2 ) + x A o d d ( x 2 ) A ( − x ) = A e v e n ( x 2 ) − x A o d d ( x 2 ) A(x)=A_{even}(x^2)+xA_{odd}(x^2) \\ A(-x)=A_{even}(x^2)-xA_{odd}(x^2) A(x)=Aeven(x2)+xAodd(x2)A(x)=Aeven(x2)xAodd(x2)带入 ± 1 \pm 1 ±1 A ( 1 ) = A e v e n ( 1 ) + x A o d d ( 1 ) A ( − 1 ) = A e v e n ( 1 ) − A o d d ( 1 ) A(1)=A_{even}(1)+xA_{odd}(1) \\ A(-1)=A_{even}(1)-A_{odd}(1) A(1)=Aeven(1)+xAodd(1)A(1)=Aeven(1)Aodd(1)可以通过在一点处求 2 个 n − 1 2 \frac{n-1}{2} 2n1 次多项式来求 2 个点上 n − 1 n-1 n1 次多项式的值。

如果在此基础上再引入复数 i i i 那么你将会看到如下光景: A ( 1 ) = A e v e n ( 1 ) + A o d d ( 1 ) A ( − 1 ) = A e v e n ( 1 ) − A o d d ( 1 ) A ( i ) = A e v e n ( − 1 ) + i A o d d ( − 1 ) A ( − i ) = A e v e n ( − 1 ) − i A o d d ( − 1 ) A(1)=A_{even}(1)+A_{odd}(1) \\ A(-1)=A_{even}(1)-A_{odd}(1) \\ A(i)=A_{even}(-1)+iA_{odd}(-1) \\ A(-i)=A_{even}(-1)-iA_{odd}(-1) A(1)=Aeven(1)+Aodd(1)A(1)=Aeven(1)Aodd(1)A(i)=Aeven(1)+iAodd(1)A(i)=Aeven(1)iAodd(1)可以通过在二个点上求 2 个 n − 1 2 \frac{n-1}{2} 2n1 次多项式来求 4 个点上 n − 1 n-1 n1 次多项式的值。

利用对称性(相反数),我们可以实现一穿二的计算速度,换句话说,计算速度翻倍。


3. 离散傅里叶 DFT 和单位根

在这里插入图片描述
单位根(Roots of Unity)是复数域中的一组特殊复数,它们是复数平面上的单位长度向量,分布在圆周上,且相邻单位根之间的夹角相等,相邻单位根之间的夹角为 2 π / n 2π/n 2π/n 弧度。

具体来说,一个 n n n 次单位根是复数 ω \omega ω,满足条件: ω n = 1 \omega^n=1 ωn=1

单位根是使得其 n 次幂等于1的复数

单位根可以用复数的指数形式表示为: ω k = e 2 π i k n ​ \omega_k = e^{\frac{2πik}{n}}​ ωk=en2πik

回到下面这个式子:

给定多项式 a ( x ) = a 0 + a 1 x + … + a n − 1 x n − 1 a (x) = a_0 + a_1x +…+ a_{n-1} x_{n - 1} a(x)=a0+a1x++an1xn1,在 n n n 个不同的点处求值 x 0 , … , x n − 1 x_0,…, x_{n-1} x0,,xn1: [ y 0 y 1 y 2 ⋮ y n − 1 ] = [ 1 x 0 x 0 2 … x 0 n − 1 1 x 1 x 1 2 … x 1 n − 1 1 x 2 x 2 2 … x 2 n − 1 ⋮ ⋮ ⋮ ⋱ ⋮ 1 x n − 1 x n − 1 2 … x n − 1 n − 1 ] [ a 0 a 1 a 2 ⋮ a n − 1 ] \begin{bmatrix}y_0\\y_1\\y_2\\\vdots \\y_{n-1}\end{bmatrix} = \begin{bmatrix} 1& x_0& x_0^2 & \dots &x_0^{n-1} \\ 1& x_1& x_1^2 & \dots & x_1^{n-1}\\ 1& x_2& x_2^2 & \dots & x_2^{n-1}\\ \vdots & \vdots & \vdots & \ddots & \vdots\\ 1& x_{n-1} & x_{n-1}^2 & \dots & x_{n-1}^{n-1} \end{bmatrix}\begin{bmatrix}a_0\\a_1\\a_2\\\vdots\\a_{n-1}\end{bmatrix} y0y1y2yn1 = 1111x0x1x2xn1x02x12x22xn12x0n1x1n1x2n1xn1n1 a0a1a2an1

将其中的 x i x_i xi 用单位根 ω \omega ω 进行替换可得:

[ y 0 y 1 y 2 ⋮ y n − 1 ] = [ 1 1 1 … 1 1 ω 1 ω 2 … ω n − 1 1 ω 2 ω 4 … ω 2 ( n − 1 ) ⋮ ⋮ ⋮ ⋱ ⋮ 1 ω n − 1 ω 2 ( n − 1 ) … ω ( n − 1 ) ( n − 1 ) ] [ a 0 a 1 a 2 ⋮ a n − 1 ] \begin{bmatrix}y_0\\y_1\\y_2\\\vdots \\y_{n-1}\end{bmatrix} =\begin{bmatrix} 1& 1& 1 & \dots &1\\ 1& \omega^1& \omega^2 & \dots & \omega^{n-1}\\ 1& \omega^2& \omega^4 & \dots & \omega^{2(n-1)}\\ \vdots & \vdots & \vdots & \ddots & \vdots\\ 1& \omega^{n-1} & \omega^{2(n-1)} & \dots & \omega^{(n-1)(n-1)} \end{bmatrix}\begin{bmatrix}a_0\\a_1\\a_2\\\vdots\\a_{n-1}\end{bmatrix} y0y1y2yn1 = 11111ω1ω2ωn11ω2ω4ω2(n1)1ωn1ω2(n1)ω(n1)(n1) a0a1a2an1 其中 y k = A ( ω k ) y_k=A(\omega^k) yk=A(ωk) ω i \omega^i ωi 为傅里叶矩阵。


FFT

给定多项式 A ( x ) = a 0 + a 1 x + … + a n − 1 x n − 1 A (x) = a_0 + a_1x +…+ a_{n-1} x_{n - 1} A(x)=a0+a1x++an1xn1,在 n t h n^{th} nth 单位根处求值 ω 0 , ω 1 , … , ω n − 1 \omega^0,\omega^1,…, \omega^{n-1} ω0,ω1,,ωn1

拆解: A e v e n ( x ) = a 0 + a 2 x + a 4 x 2 + . . . + a n − 2 x n / 2 − 1 A o d d ( x ) = a 1 + a 3 x + a 5 x 2 + . . . + a n − 1 x n / 2 − 1 A_{even}(x)=a_0+a_2x+a_4x^2+...+a_{n-2}x^{n/2-1} \\ A_{odd}(x)=a_1+a_3x+a_5x^2+...+a_{n-1}x^{n/2-1} Aeven(x)=a0+a2x+a4x2+...+an2xn/21Aodd(x)=a1+a3x+a5x2+...+an1xn/21 A ( x ) = A e v e n ( x 2 ) + x A o d d ( x 2 ) A ( − x ) = A e v e n ( x 2 ) − x A o d d ( x 2 ) A(x)=A_{even}(x^2)+xA_{odd}(x^2) \\ A(-x)=A_{even}(x^2)-xA_{odd}(x^2) A(x)=Aeven(x2)+xAodd(x2)A(x)=Aeven(x2)xAodd(x2)
求解:求 A e v e n ( x ) A_{even}(x) Aeven(x) A o d d ( x ) A_{odd}(x) Aodd(x)和在单位的 n t h 2 \frac{n^{th}}{2} 2nth 根处的值: v 0 , v 1 , … , v n / 2 − 1 v^0,v^1,…,v^{n/ 2-1} v0v1,,vn/21

合并: y k = A ( ω k ) = A e v e n ( v k ) + ω k A o d d ( v k ) , 0 ≤ k ≤ n / 2 y k + n / 2 = A ( ω k + n / 2 ) = A e v e n ( v k ) − ω k A o d d ( v k ) , 0 ≤ k ≤ n / 2 y_k=A(\omega^k)=A_{even}(v^k)+\omega^kA_{odd}(v^k),0\le k \le n/2 \\ y_{k+n/2}=A(\omega^{k+n/2})=A_{even}(v^k)-\omega^kA_{odd}(v^k),0\le k \le n/2 yk=A(ωk)=Aeven(vk)+ωkAodd(vk),0kn/2yk+n/2=A(ωk+n/2)=Aeven(vk)ωkAodd(vk),0kn/2其中 v k = ( ω k ) 2 , ω k + n / 2 = − ω k v^k=(\omega^k)^2,\omega^{k+n/2}=-\omega^k vk=(ωk)2,ωk+n/2=ωk

在这里插入图片描述
T ( n ) = { Θ ( 1 ) 2 T ( n / 2 ) + Θ ( n ) T(n)=\left\{\begin{matrix} \Theta (1) \\2T(n/2)+\Theta (n) \end{matrix}\right. T(n)={Θ(1)2T(n/2)+Θ(n)


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1152020.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PandaX : Go语言企业级 IoT 物联网平台快速开发框架

PandaX 是一个基于前后端分离架构开发的开源企业级物联网平台低代码开发基座&#xff0c;后端系统采用 Go 语言和前端基于 VUE3 开发&#xff0c;支持设备接入、设备管控&#xff0c;规则链引擎&#xff0c;云组态&#xff0c;可视化大屏&#xff0c;报表设计器&#xff0c;表单…

STM32智能小车—跟随小车和摇头避障小车

一、STM32跟随小车 1. 红外壁障模块分析 原理和循迹是一样的&#xff0c;循迹红外观朝下&#xff0c;跟随朝前 2. 跟随小车的原理 左边跟随模块能返回红外&#xff0c;输出低电平&#xff0c;右边不能返回&#xff0c;输出高电平&#xff0c;说明物体在左边&#xff0c;需要…

Python基础入门例程26-NP26 牛牛的反转列表(列表)

最近的博文&#xff1a; Python基础入门例程25-NP25 有序的列表&#xff08;列表&#xff09;-CSDN博客 Python基础入门例程24-NP24 淘汰排名最后的学生&#xff08;列表&#xff09;-CSDN博客 Python基础入门例程23-NP23 删除好友&#xff08;列表&#xff09;-CSDN博客 目录 …

随机链表的复制(C++解法)

题目 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的原节点的值。新节…

Go Map底层实现简述

Go的map是一种高效的数据结构&#xff0c;用于存储键值对。其底层实现是一个哈希表&#xff08;hash table&#xff09;&#xff0c;下面是有关map底层实现的详细介绍&#xff1a; 哈希表&#xff1a; map的底层实现是一个哈希表&#xff0c;也称为散列表。哈希表是一个数组&a…

轻量封装WebGPU渲染系统示例<8>- 渲染器基本场景管理(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/main/src/voxgpu/sample/RSceneTest.ts 此示例渲染系统实现的特性: 1. 用户态与系统态隔离。 2. 高频调用与低频调用隔离。 3. 面向用户的易用性封装。 4. 渲染数据和渲染机制分离。 5. 用户操作和渲…

【JavaSE专栏58】“Java构造函数:作用、类型、调用顺序和最佳实践“ ⚙️⏱️

解析Java构造函数&#xff1a;作用、类型、调用顺序和最佳实践" &#x1f680;&#x1f4da;&#x1f50d;&#x1f914;&#x1f4dd;&#x1f504;⚙️⏱️&#x1f4d6;&#x1f310; 摘要引言1. 什么是构造函数 &#x1f914;2. 构造函数的类型与用途 &#x1f4dd;1.…

nodejs+vue学生考勤综合平台的设计与实现-计算机毕业设计

在当今高度发达的信息中&#xff0c;信息管理改革已成为一种更加广泛和全面的趋势。 “学生考勤综合平台”是基于Mysql数据库&#xff0c;在 程序设计的基础上实现的。为确保中国经济的持续发展&#xff0c;信息时代日益更新&#xff0c;蓬勃发展。 因此&#xff0c;国内外技术…

骑行在路上,VELO Swan O带你感受生活真实的呼吸

过去&#xff0c;人们骑车是为了更快抵达更远的地方。如今&#xff0c;越来越多身处快节奏生活环境中的都市人&#xff0c;正在通过骑行“慢”下来。骑着车穿梭在城市间&#xff0c;暂时跳脱出两点一线的既定模式&#xff0c;在路途上感受人与环境一切微妙的变化&#xff0c;真…

python爬虫报错:This version of ChromeDriver only supports Chrome version 114

使用selenium爬取网页数据&#xff0c;一运行程序就报错&#xff1a; selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 114 Current browser version is 117.0.5938.149 w…

zookeeper:简介及常用命令

目录 一、Zookeeper简介 二、Zookeeper服务端常用命令 1、启动ZooKeeper服务 2、查看ZooKeeper服务状态 3、停止ZooKeeper服务 4、重启ZooKeeper服务 三、Zookeeper客户端常用命令 1、连接ZooKeeper服务端 2、断开连接&#xff1a;quit 3、查看命令帮助&#xff1a;help…

【C++进阶】异常

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

MATLAB | 万圣节来画个简单的可爱鬼叭!

万圣节要到啦一起来画个可爱鬼吧~ 代码比较的短&#xff1a; 完整代码 figure(Units,normalized,Position,[.2,.1,.52,.72]); axgca;hold on;axis off; ax.DataAspectRatio[1,1,1]; ax.YDirreverse; ax.XLim[0,100]; ax.YLim[0,100]; [X,Y]meshgrid(linspace(0,1,200)); Zsq…

当任务数超过线程池的核心线程数时,如何让它不进入队列,而是直接启用最大线程数

线程池工作原理 当我们提交一个任务到线程池的时候&#xff0c;它的工作原理分为四步&#xff1a; 第一步&#xff0c;预热核心线程 第二步&#xff0c;把任务添加到阻塞队列 第三步&#xff0c;如果添加到阻塞队列失败&#xff0c;则创建非核心线程增加处理效率 第四步&#x…

nodejs+python+php+微信小程序-基于安卓android的健身服务应用APP-计算机毕业设计

考虑到实际生活中在健身服务应用方面的需要以及对该系统认真的分析&#xff0c;将系统权限按管理员和用户这两类涉及用户划分。  则对于进一步提高健身服务应用发展&#xff0c;丰富健身服务应用经验能起到不少的促进作用。 健身服务应用APP能够通过互联网得到广泛的、全面的宣…

轻量封装WebGPU渲染系统示例<10>- 容器(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/main/src/voxgpu/sample/REntity3DContainerTest.ts 此示例渲染系统实现的特性: 1. 用户态与系统态隔离。 2. 高频调用与低频调用隔离。 3. 面向用户的易用性封装。 4. 渲染数据和渲染机制分离。 5.…

Doris数据库FE——全局事务状态机

begin; create database db1; ERROR 1105 (HY000): TException, msg: org.apache.thrift.TException: This is in a transaction, only insert, commit, rollback is acceptable从上述报错可以看出begin、commit、rollback等操作只有和insert操作结合使用。从上述可以猜测Doris…

【腾学汇的第1个实验代码】应用Matplotlib绘制图标分析

import matplotlib.pyplot as plt import numpy as np #Jupter Notebook 里面显示图片 %matplotlib inline#1.1.1 线形图 np.random.seed(42) #产生随机种子 y np.random.randn(30) #产生随机数 plt.plot(y, "r--o")#绘图&#xff1a;红色--虚线--圆形# 1.1.2 线条颜…

【【哈希应用】位图/布隆过滤器】

位图/布隆过滤器 位图位图概念位图的使用位图模拟实现 布隆过滤器布隆过滤器概念布隆过滤器的使用布隆过滤器模拟实现 位图/布隆过滤器应用&#xff1a;海量数据处理哈希切分 位图 位图概念 计算机中通常以位bit为数据最小存储单位&#xff0c;只有0、1两种二进制状态&#x…

2D网页游戏开发引擎

2D网页开发引擎是用于创建富有交互性和动画效果的2D网页应用程序的工具。以下是一些常用的2D网页开发引擎以及它们的主要特点&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.Phaser&#xff1a; P…