@算法 - [email protected] 多项式的多点求值与快速插值

目录

  • @0 - 参考资料@
  • @1 - 多点求值@
    • @理论推导@
    • @参考代码@
    • @例题与应用@
  • @2 - 快速插值@
    • @理论推导@
    • @(不建议参考的)代码@
    • @例题与应用@(暂无)

@0 - 参考资料@

Cyhlnj 的博客

@1 - 多点求值@

@理论推导@

假设已知多项式 \(A(x)\),使用 FFT 可以将 \(A(w_n^0)\),\(A(w_n^1)\),...,\(A(w_n^{n-1})\) 的值在 \(O(n\log n)\) 的时间内快速求出。

那么问题来了,假如我现在要求解任意的 \(A(x_0)\),\(A(x_1)\),...,\(A(x_{n-1})\) 该怎么办呢?难道只有 \(O(n^2)\) 的算法吗?

当然不是。

我们依照直觉把 \(x_{0\dots {n-1}}\) 分为两个集合:

\[S_l=\{x_0,x_1,\dots x_{\frac{n}{2}}\}\S_r=\{x_{\frac{n}{2}+1},x_{\frac{n}{2}+2},\dots x_{n-1}\}\\\]

然后,记多项式 \(P_l(x)=\prod_{x_i\in S_L}(x-x_i)\),并用 \(A(x)\) 除以 \(P_l(x)\),得到:

\[A(x)=P_l(x)*Q(x)+R_l(x)\]

这样当 \(x_i\in S_l\) 时,\(P_l(x_i)=0\),\(A(x_i) = R_l(x_i)\)。

同理我们可以对 \(S_r\) 进行相应的处理。

问题转换为 \(S_l\) 对 \(R_l(x)\) 求值,\(S_r\) 对 \(R_r(x)\) 求值。

然后就可以分治了。到底层时 \(R(x)\) 就是一个常数,可以直接赋值。

\(P_l(x)\) 与 \(P_r(x)\) 可以利用类线段树的方法处理与储存下来。

一个细节:如果 \(A(x)\) 的最高次数高于 \(\prod_{x=0}^{N-1}(x-x_i)\),则先 \(A(x)\) 模一下 \(\prod_{x=0}^{N-1}(x-x_i)\)。

复杂度为 \(O(n\log^2n)\)。

@参考代码@

本代码为 luoguP5050 的 AC 代码。

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int G = 3;
const int MOD = 998244353;
const int MAXN = 64000*10;
int pow_mod(int b, int p) {
    int ret = 1;
    while( p ) {
        if( p & 1 ) ret = 1LL*ret*b%MOD;
        b = 1LL*b*b%MOD;
        p >>= 1;
    }
    return ret;
}
struct Polynomial{
    void poly_copy(int *A, int *B, int n) {
        for(int i=0;i<n;i++)
            A[i] = B[i];
    }
    void poly_clear(int *A, int l, int r) {
        for(int i=l;i<r;i++)
            A[i] = 0;
    }
    void poly_revcopy(int *A, int *B, int n) {
        for(int i=0;i<n;i++)
            A[i] = B[n-i-1];
    }
    void ntt(int *A, int n, int type) {
        for(int i=0,j=0;i<n;i++) {
            if( i < j ) swap(A[i], A[j]);
            for(int l=(n>>1);(j^=l)<l;l>>=1);
        }
        for(int s=2;s<=n;s<<=1) {
            int t = (s>>1);
            int u = (type == -1) ? pow_mod(G, (MOD-1) - (MOD-1)/s) : pow_mod(G, (MOD-1)/s);
            for(int i=0;i<n;i+=s) {
                for(int j=0,p=1;j<t;j++,p=1LL*p*u%MOD) {
                    int x = A[i+j], y = 1LL*p*A[i+j+t]%MOD;
                    A[i+j] = (x + y)%MOD, A[i+j+t] = (x + MOD - y)%MOD;
                }
            }
        }
        if( type == -1 ) {
            int inv = pow_mod(n, MOD-2);
            for(int i=0;i<n;i++)
                A[i] = 1LL*A[i]*inv%MOD;
        }
    }
    int tmp1[MAXN + 5], tmp2[MAXN + 5], tmp3[MAXN + 5];
    void poly_mul(int *A, int *B, int *C, int n, int m) {
        int len; for(len = 1;len < n+m-1;len <<= 1);
        poly_copy(tmp1, A, n); poly_clear(tmp1, n, len);
        poly_copy(tmp2, B, m); poly_clear(tmp2, m, len);
        ntt(tmp1, len, 1); ntt(tmp2, len, 1);
        for(int i=0;i<len;i++) tmp3[i] = 1LL*tmp1[i]*tmp2[i]%MOD;
        ntt(tmp3, len, -1); poly_copy(C, tmp3, n+m-1);
    }
    void poly_inv(int *A, int *B, int n) {
        if( n == 1 ) {
            B[0] = pow_mod(A[0], MOD-2);
            return ;
        }
        int len; for(len = 1;len < (n<<1);len <<= 1);
        poly_inv(A, B, (n + 1) >> 1);
        poly_copy(tmp3, A, n); poly_clear(tmp3, n, len);
        ntt(tmp3, len, 1); ntt(B, len, 1);
        for(int i=0;i<len;i++) B[i] = 1LL*B[i]*(2 + MOD - 1LL*tmp3[i]*B[i]%MOD)%MOD;
        ntt(B, len, -1); poly_clear(B, n, len);
    }
    int tmp4[MAXN + 5], tmp5[MAXN + 5], tmp6[MAXN + 5];
    void poly_divide(int *A, int *B, int *C, int *R, int n, int m) {
        poly_revcopy(tmp4, B, m); poly_clear(tmp5, 0, 2*(n-m+1)); poly_inv(tmp4, tmp5, n-m+1);
        poly_revcopy(tmp4, A, n); poly_mul(tmp4, tmp5, tmp6, n-m+1, n-m+1);
        poly_revcopy(C, tmp6, n-m+1);

        poly_copy(tmp4, C, n-m+1); poly_copy(tmp5, B, m);
        poly_mul(tmp4, tmp5, tmp6, n-m+1, m);
        for(int i=0;i<m-1;i++) R[i] = (A[i] + MOD - tmp6[i])%MOD;
    }
    void poly_mod(int *A, int *B, int *R, int n, int m) {
        if( n < m ) {
            for(int i=0;i<m-1;i++) R[i] = A[i];
            return ;
        }
        poly_revcopy(tmp4, B, m); poly_inv(tmp4, tmp5, n-m+1);
        poly_revcopy(tmp4, A, n); poly_mul(tmp4, tmp5, tmp6, n-m+1, n-m+1);

        poly_revcopy(tmp4, tmp6, n-m+1); poly_copy(tmp5, B, m);
        poly_mul(tmp4, tmp5, tmp6, n-m+1, m);
        for(int i=0;i<m-1;i++) R[i] = (A[i] + MOD - tmp6[i])%MOD;
        poly_clear(tmp4, 0, n); poly_clear(tmp5, 0, n);
    }
    vector<int>P[MAXN + 5];
    void poly_build(int *X, int x, int l, int r) {
        if( l == r ) {
            P[x].push_back(MOD-X[l]), P[x].push_back(1);
            return ;
        }
        int mid = (l + r) >> 1;
        poly_build(X, x<<1, l, mid), poly_build(X, x<<1|1, mid+1, r);
        for(int i=0;i<P[x<<1].size();i++) tmp4[i] = P[x<<1][i];
        for(int i=0;i<P[x<<1|1].size();i++) tmp5[i] = P[x<<1|1][i];
        poly_mul(tmp4, tmp5, tmp6, P[x<<1].size(), P[x<<1|1].size());
        for(int i=0;i<P[x<<1].size()+P[x<<1|1].size()-1;i++) P[x].push_back(tmp6[i]);
        poly_clear(tmp4, 0, P[x<<1].size()), poly_clear(tmp5, 0, P[x<<1|1].size());
    }
    int tmp7[MAXN + 5], tmp8[25][MAXN + 5];
    void poly_eval(int *A, int *Y, int dep, int n, int l, int r, int x) {
        for(int i=0;i<P[x].size();i++) tmp7[i] = P[x][i];
        poly_mod(A, tmp7, tmp8[dep], n, P[x].size());
        if( l == r ) {
            Y[l] = tmp8[dep][0];
            return ;
        }
        int mid = (l + r) >> 1;
        poly_eval(tmp8[dep], Y, dep+1, P[x].size()-1, l, mid, x<<1);
        poly_eval(tmp8[dep], Y, dep+1, P[x].size()-1, mid+1, r, x<<1|1);
        poly_clear(tmp8[dep], 0, P[x].size()-1);
    }
}oper;
int f[MAXN + 5], a[MAXN + 5], g[MAXN + 5];
int main() {
    int n, m; scanf("%d%d", &n, &m); n++;
    for(int i=0;i<n;i++)
        scanf("%d", &f[i]);
    for(int i=0;i<m;i++)
        scanf("%d", &a[i]);
    oper.poly_build(a, 1, 0, m-1);
    oper.poly_eval(f, g, 0, n, 0, m-1, 1);
    for(int i=0;i<m;i++)
        printf("%d\n", g[i]);
}

@例题与应用@

@快速插值@

就是下面那个东西,对,它就是多点求值的一个应用。

@2 - 快速插值@

@理论推导@

这个才是真正的毒瘤……

我们已知任意的 N+1 个点 \((x_0,y_0)\),\((x_1,y_1)\),...,\((x_N,y_N)\),想要还原一个多项式 \(A(x)\) 使得 \(A(x_i)=y_i\)。

首先来看一个东西,拉格朗日插值

\[f(x) = \sum_{i=0}^{N}(\dfrac{\prod_{j=0,j\not =i}^{N}(x-x_j)}{\prod_{j=0,j\not =i}^{N}(x_i-x_j)})*y_i\]

怎么证明呢?其实比较简单。首先证明其正确性:

记 \(P_i(x)=(\dfrac{\prod_{j=0,j\not =i}^{N}(x-x_j)}{\prod_{j=0,j\not =i}^{N}(x_i-x_j)})*y_i\),

当 \(i = j\) 时,分子等于分母, \(P_i(x_j) = y_i\);

当 \(i\not = j\) 时,分子等于零, \(P_i(x_j) = 0\)。

故 \(f(x_i)=\sum_{j=0}^{N}P_j(x_i)=y_i\)。

然后证明其唯一性,可以采用线性方程组的方法。

但是……我们如果暴力来化简上面那个式子,时间复杂度就高上天了。

所以我们接下来就来乱搞一下。

首先求解分母的部分,即 \(\prod_{j=0,j\not =i}^{N}(x_i-x_j)\) 的值。

记 \(g(x) = \prod_{i=0}^N(x-x_i)\),则我们相当于是求解:

\[\lim_{x->x_i}\dfrac{g(x)}{(x-x_i)}\]

当 \(x = x_i\) 时分母是等于 0 的,没有意义,所以我们写成极限的形式。

根据洛必达法则:

\[\lim_{x->x_i}\dfrac{g(x)}{(x-x_i)}=g‘(x)\]

即我们相当于要求解 \(g‘(x_0)\),\(g‘(x_1)\),...,\(g‘(x_N)\),快速插值即可。

……我相信你们应该会一些简单的微积分吧。

算了不重要,我继续往下讲。

【高能预警】下面的公式非常密集,请做好心理准备。

记 \(k_i = \dfrac{y_i}{\prod_{j=0,j\not =i}^{N}(x_i-x_j)}\),分子已知,分母可以通过我们上边的方法求解。

则原式变为:

\[f(x)=\sum_{i=0}^{N}k_i*(\prod_{j=0,j\not =i}^{N}(x-x_j))\]

记 \(P_l(x)=\prod_{i=0}^{\frac{N}{2}}(x-x_i)\),\(P_r(x)=\prod_{i=\frac{N}{2}+1}^{N}(x-x_i)\)。

再记 \(f_l(x)=\sum_{i=0}^{\frac{N}{2}}k_i*(\prod_{j=0,j\not =i}^{\frac{N}{2}}(x-x_j))\),\(f_r(x)=\sum_{i=\frac{N}{2}+1}^{N}k_i*(\prod_{j=\frac{N}{2}+1,j\not =i}^{N}(x-x_j))\)

则 \(f(x)\) 可以写成:

\[f(x)=P_r(x)*f_l(x)+P_l(x)*f_r(x)\]

预处理出 \(P(x)\),分治即可。最底层直接返回 \(k_i\)。

怎么理解呢?对于 \(h_i(x) = k_i*(\prod_{j=0,j\not =i}^{N}(x-x_j))\),它 “缺” \((x-x_i)\) 这一项。

对于 \(0\le i\le \frac{N}{2}\),它们都不 “缺” \((x-x_j),\frac{N}{2}+1\le j\le N\) 这一项。

所以利用乘法分配律,就可以得到上面那个式子。

一个细节:多点求值用的 \(P(x)\) 与快速插值后面分治用的 \(P(x)\) 是同一个玩意儿,所以可以不用重复求解。

时间复杂度:\(O(n\log^2n)\),常数极大。

@(不建议参考的)代码@

本代码为 luoguP5518 的 AC 代码

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int G = 3;
const int MOD = 998244353;
const int MAXN = 100000*10;
int pow_mod(int b, int p) {
    int ret = 1;
    while( p ) {
        if( p & 1 ) ret = 1LL*ret*b%MOD;
        b = 1LL*b*b%MOD;
        p >>= 1;
    }
    return ret;
}
int inv[MAXN + 5];
void init() {
    inv[1] = 1;
    for(int i=2;i<=MAXN;i++)
        inv[i] = 1LL*(MOD - MOD/i)*inv[MOD%i]%MOD;
}
struct Polynomial{
    void poly_copy(int *A, int *B, int n) {
        for(int i=0;i<n;i++)
            A[i] = B[i];
    }
    void poly_copy(int *A, vector<int> B) {
        for(int i=0;i<B.size();i++)
            A[i] = B[i];
    }
    void poly_clear(int *A, int l, int r) {
        for(int i=l;i<r;i++)
            A[i] = 0;
    }
    void poly_revcopy(int *A, int *B, int n) {
        for(int i=0;i<n;i++)
            A[i] = B[n-i-1];
    }
    void ntt(int *A, int n, int type) {
        for(int i=0,j=0;i<n;i++) {
            if( i < j ) swap(A[i], A[j]);
            for(int l=(n>>1);(j^=l)<l;l>>=1);
        }
        for(int s=2;s<=n;s<<=1) {
            int t = (s>>1);
            int u = (type == -1) ? pow_mod(G, (MOD-1) - (MOD-1)/s) : pow_mod(G, (MOD-1)/s);
            for(int i=0;i<n;i+=s) {
                for(int j=0,p=1;j<t;j++,p=1LL*p*u%MOD) {
                    int x = A[i+j], y = 1LL*p*A[i+j+t]%MOD;
                    A[i+j] = (x + y)%MOD, A[i+j+t] = (x + MOD - y)%MOD;
                }
            }
        }
        if( type == -1 ) {
            int inv = pow_mod(n, MOD-2);
            for(int i=0;i<n;i++)
                A[i] = 1LL*A[i]*inv%MOD;
        }
    }
    int tmp1[MAXN + 5], tmp2[MAXN + 5], tmp3[MAXN + 5];
    void poly_mul(int *A, int *B, int *C, int n, int m) {
        int len; for(len = 1;len < n+m-1;len <<= 1);
        poly_copy(tmp1, A, n); poly_clear(tmp1, n, len);
        poly_copy(tmp2, B, m); poly_clear(tmp2, m, len);
        ntt(tmp1, len, 1); ntt(tmp2, len, 1);
        for(int i=0;i<len;i++) tmp3[i] = 1LL*tmp1[i]*tmp2[i]%MOD;
        ntt(tmp3, len, -1); poly_copy(C, tmp3, n+m-1);
    }
    void poly_inv(int *A, int *B, int n) {
        if( n == 1 ) {
            B[0] = pow_mod(A[0], MOD-2);
            return ;
        }
        int len; for(len = 1;len < (n<<1);len <<= 1);
        poly_inv(A, B, (n + 1) >> 1);
        poly_copy(tmp3, A, n); poly_clear(tmp3, n, len);
        ntt(tmp3, len, 1); ntt(B, len, 1);
        for(int i=0;i<len;i++) B[i] = 1LL*B[i]*(2 + MOD - 1LL*tmp3[i]*B[i]%MOD)%MOD;
        ntt(B, len, -1); poly_clear(B, n, len);
    }
    int tmp4[MAXN + 5], tmp5[MAXN + 5], tmp6[MAXN + 5];
    void poly_divide(int *A, int *B, int *C, int *R, int n, int m) {
        poly_revcopy(tmp4, B, m); poly_clear(tmp5, 0, 2*(n-m+1)); poly_inv(tmp4, tmp5, n-m+1);
        poly_revcopy(tmp4, A, n); poly_mul(tmp4, tmp5, tmp6, n-m+1, n-m+1);
        poly_revcopy(C, tmp6, n-m+1);

        poly_copy(tmp4, C, n-m+1); poly_copy(tmp5, B, m);
        poly_mul(tmp4, tmp5, tmp6, n-m+1, m);
        for(int i=0;i<m-1;i++) R[i] = (A[i] + MOD - tmp6[i])%MOD;
    }
    void poly_mod(int *A, int *B, int *R, int n, int m) {
        if( n < m ) {
            for(int i=0;i<m-1;i++) R[i] = A[i];
            return ;
        }
        poly_revcopy(tmp4, B, m); poly_inv(tmp4, tmp5, n-m+1);
        poly_revcopy(tmp4, A, n); poly_mul(tmp4, tmp5, tmp6, n-m+1, n-m+1);

        poly_revcopy(tmp4, tmp6, n-m+1); poly_copy(tmp5, B, m);
        poly_mul(tmp4, tmp5, tmp6, n-m+1, m);
        for(int i=0;i<m-1;i++) R[i] = (A[i] + MOD - tmp6[i])%MOD;
        poly_clear(tmp4, 0, n); poly_clear(tmp5, 0, n);
    }
    vector<int>P[MAXN + 5];
    void poly_build(int *X, int x, int l, int r) {
        if( l == r ) {
            P[x].clear(); P[x].push_back(MOD-X[l]), P[x].push_back(1);
            return ;
        }
        int mid = (l + r) >> 1;
        poly_build(X, x<<1, l, mid), poly_build(X, x<<1|1, mid+1, r);
        poly_copy(tmp4, P[x<<1]), poly_copy(tmp5, P[x<<1|1]);
        poly_mul(tmp4, tmp5, tmp6, P[x<<1].size(), P[x<<1|1].size()); P[x].clear();
        for(int i=0;i<P[x<<1].size()+P[x<<1|1].size()-1;i++) P[x].push_back(tmp6[i]);
        poly_clear(tmp4, 0, P[x<<1].size()), poly_clear(tmp5, 0, P[x<<1|1].size());
    }
    int tmp7[MAXN + 5], tmp8[25][MAXN + 5];
    void poly_eval(int *A, int *Y, int dep, int n, int l, int r, int x) {
        for(int i=0;i<P[x].size();i++) tmp7[i] = P[x][i];
        poly_mod(A, tmp7, tmp8[dep], n, P[x].size());
        if( l == r ) {
            Y[l] = tmp8[dep][0];
            return ;
        }
        int mid = (l + r) >> 1;
        poly_eval(tmp8[dep], Y, dep+1, P[x].size()-1, l, mid, x<<1);
        poly_eval(tmp8[dep], Y, dep+1, P[x].size()-1, mid+1, r, x<<1|1);
        poly_clear(tmp8[dep], 0, P[x].size()-1);
    }
    void poly_dif(int *A, int *B, int n) {
        for(int i=1;i<n;i++)
            B[i-1] = 1LL*A[i]*i%MOD;
        B[n-1] = 0;
    }
    void poly_itgr(int *A, int *B, int n) {
        for(int i=n-1;i>=0;i--)
            B[i+1] = 1LL*A[i]*inv[i+1]%MOD;
    }
    int tmp9[MAXN + 5], tmp10[MAXN + 5], tmp11[25][MAXN + 5], tmp12[MAXN + 5];
    void poly_itplt(int *A, int dep, int x, int l, int r) {
        poly_clear(A, 0, P[x].size());
        if( l == r ) {
            A[0] = tmp10[l];
            return ;
        }
        int mid = (l + r) >> 1;
        poly_itplt(tmp11[dep], dep+1, x<<1, l, mid);
        poly_copy(tmp9, P[x<<1|1]); poly_mul(tmp9, tmp11[dep], tmp12, P[x<<1|1].size(), P[x<<1].size());
        for(int i=0;i<P[x].size();i++) A[i] = (A[i] + tmp12[i])%MOD;
        poly_itplt(tmp11[dep], dep+1, x<<1|1, mid+1, r);
        poly_copy(tmp9, P[x<<1]); poly_mul(tmp9, tmp11[dep], tmp12, P[x<<1].size(), P[x<<1|1].size());
        for(int i=0;i<P[x].size();i++) A[i] = (A[i] + tmp12[i])%MOD;
    }
    void poly_itplt(int *X, int *Y, int *A, int n) {
        poly_build(X, 1, 0, n-1); poly_copy(tmp9, P[1]);
        poly_dif(tmp9, tmp9, P[1].size());
        poly_eval(tmp9, tmp10, 0, P[1].size()-1, 0, n-1, 1);
        for(int i=0;i<n;i++) tmp10[i] = 1LL*Y[i]*pow_mod(tmp10[i], MOD-2)%MOD;
        poly_itplt(A, 0, 1, 0, n-1);
    }
}oper;
int x[MAXN + 5], y[MAXN + 5], f[MAXN + 5];
int main() {
    int n; scanf("%d", &n);
    for(int i=0;i<n;i++)
        scanf("%d%d", &x[i], &y[i]);
    oper.poly_itplt(x, y, f, n);
    for(int i=0;i<n;i++)
        printf("%d ", f[i]);
}

@例题与应用@(暂无)

这个东西……能够应用???

原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/10198693.html

时间: 2024-08-06 19:13:56

@算法 - [email protected] 多项式的多点求值与快速插值的相关文章

多点求值与快速插值

多点求值 给出 $n$ 次多项式 $A(x)$ ,求出 $m$ 个 $x_i$ 对应的 $A(x_i)$ 考虑分治,设 $L(x)=\prod_{i=1}^{\frac{n}{2}}(x-x_i)$ , $R(x)=\prod_{i=\frac{n}{2}+1}^n(x-x_i)$ 对于 $i \in [1,\frac{n}{2}],F(x_i)=(F \mod L)(x_i)$ , 对于 $i \in (\frac{n}{2},n],F(x_i)=(F \mod R)(x_i)$ 就是对于左半

多点求值与暴力插值

暴力插值 给你 \(n\) 个点 \((x_i,y_i)\) ,要求求出这个 \(n\) 次多项式 \(F(x)\) 我们有 \[ F(x)=\sum_{i=1}^ny_i\frac{\!\prod\limits_{1\le j\le n,i\not=j}\!\!\!\!(x-x_j)}{\!\prod\limits_{1\le j\le n,i\not=j}\!\!\!\!(x_i-x_j)} \] 感性愉悦认识一下这个拉格朗日插值 复杂度 \(O(n^2)\) 多点求值 给你 \(X=\{x

多项式多点求值和插值

本文以存板子为主= = 对于比较一般的情况,n次多项式在n个点求值和用n个点插值可以做到,并且这也是下界. 多项式多点求值 给一个多项式F和一堆值,求出. 设,. 那么对于,,对于,.递归即可. 多项式多点插值 给一堆值.,要求求出一个n-1次多项式满足. 考虑拉格朗日插值:. 我们先考虑对于每个i,如何求出.设,那么我们就是要求. 取的时候这个式子分子分母都为0,那么我们可以用洛必达法则,这个式子就等于.那么我们可以用多点求值求出每个. 设为,现在我们就是要求,显然可以分治FFT. 具体地,还

多项式函数插值:多项式形式函数求值的Horner嵌套算法

设代数式序列 $q_1(t), q_2(t), ..., q_{n-1}(t)$ ,由它们生成的多项式形式的表达式(不一定是多项式): $$p(t)=x_1+x_2q_1(t)+...x_nq_1(t)q_2(t)..q_{n-1}(t)=\sum\limits_{i=1}^n(x_i\prod\limits_{j=1}^{i-1}q_j(t))$$ 一般来讲,按照这个形式计算函数在 $t_0$ 点的取值的复杂度为:n-1次 $q_i(t)$ 求值,n-1次浮点数乘法(生成n个不同的乘积),n-

@算法 - [email&#160;protected] matrix - tree 定理(矩阵树定理)

目录 @0 - 参考资料@ @0.5 - 你所需要了解的线性代数知识@ @1 - 定理主体@ @证明 part - [email protected] @证明 part - [email protected] @证明 part - [email protected] @证明 part - 4@ @2 - 一些简单的推广@ @3 - 例题与应用@ @0 - 参考资料@ MoebiusMeow 的讲解(超喜欢这个博主的!) 网上找的另外一篇讲解 @0.5 - 你所需要了解的线性代数知识@ 什么是矩阵

@算法 - [email&#160;protected] 后缀自动机

目录 @0 - 参考资料@ @0.5 - 引言@ @1 - what is [email protected] @自动机@ @DAWG@ @终点集合 [email protected] @后缀链接 与 parent 树@ @2 - how to build [email protected] @理论@ @代码@ @3 - where can it [email protected] @0 - 参考资料@ Menci's Blog 的讲解 陈立杰冬令营的课件 @0.5 - 引言@ 后缀自动机(Su

递推求值【快速幂矩阵】

递推求值 描述 给你一个递推公式: f(x)=a*f(x-2)+b*f(x-1)+c 并给你f(1),f(2)的值,请求出f(n)的值,由于f(n)的值可能过大,求出f(n)对1000007取模后的值. 注意:-1对3取模后等于2   输入 第一行是一个整数T,表示测试数据的组数(T<=10000)随后每行有六个整数,分别表示f(1),f(2),a,b,c,n的值.其中0<=f(1),f(2)<100,-100<=a,b,c<=100,1<=n<=10000000

@算法 - [email&#160;protected] 牛顿迭代法的应用——多项式开方,对数,指数,三角与幂函数

目录 @0 - 参考资料@ @0.5 - 多项式平方根@ @1 - 牛顿迭代法@ @数学上的定义@ @对于多项式的定义@ @2 - 牛顿迭代的应用@ @重新推导 - 多项式逆元@ @重新推导 - 多项式平方根@ @多项式对数函数@ @多项式指数函数@ @多项式幂函数@ @多项式三角函数@ @3 - 一些参考代码@(留坑待填) @4 - 算法应用@(留坑待填) @0 - 参考资料@ Miskcoo's Space 的讲解 Picks 的讲解 @0.5 - 多项式平方根@ 已知一个多项式 \(A(x

多项式多点求值

给定一个\(n\)次多项式\(A(x)\)和\(m\)个值\(a_i\),求出对于\(任意i\in [0,m-1],A(a_i)\)的值 前置知识: 分治FFT 多项式除法 一般优化多项式要么倍增要么分治-- 然而这题看上去不像能倍增的亚子,所以就分治吧 考虑先将要求的点分为两部分 \(x[0]=\{x_0,x_1,--,x_{\frac{m}{2}}\},x[1]=\{x_{\frac{m}{2}+1},x_{\frac{m}{2}+2},--x_{m-1}\}\) 我们记\(p[0]=\pr