多項式簡單操作

多項式求導

原理

如果有
\[ A(x) = \sum_{i = 0}^{n} c_i x^i \]

那麼由於求導的加法原則,每一項可以單獨考慮,則有
\[ A'(x) = \sum_{i = 1}^{n} ic_ix^{i - 1} \]

實現

void Der(int *f, int *g, int lf) {
    For (i, 1, lf) g[i - 1] = 1ll * i * f[i] % Mod;
}

多項式積分

原理

如果有
\[ A(x) = \sum_{i = 0}^{n} c_i x^i \]

同樣由於積分的加法原則,每一項可以單獨考慮,則有(常數項可以忽略)
\[ \int A(x) \mathrm{d} x = \sum_{i = 1}^{n + 1} \frac{c_{i - 1}}{i} x^{i} \]

實現

void Int(int *f, int *g, int lf) {
    For (i, 1, lf + 1)
        g[i] = 1ll * f[i - 1] * inv[i] % Mod;
}

多項式牛頓迭代

原理

給出函數 \(f\) ,找到一個多項式 \(A\),使得 \(f(A(x)) \equiv 0 \pmod {x^n}\)

\(\pmod x\) 時,可以求出 \(A(x)\) 的常數項。

已經求出 \(f(A(x)) \equiv 0 \bmod {x^n}\) ,現在求 \(f(B(x)) \equiv 0 \bmod {x^{2n}}\)\(B(x)\)\(A(x)\)\(n\) 項係數相同。

\(\bmod {x^{2n}}\) 下,在 \(A(x)\) 處展開 \(f(B(x))\)
\[ f(B(x)) = \sum_{i \ge 0} \frac{f^{(i)}(A(x))}{i!}(B(x) - A(x))^i \]
不難發現在 \(i \ge 2\) 的時候,最低項已經超過了 \(x^{2n}\) ,所以只有 \(i = 0, 1\) 要考慮,也就是
\[ \begin{aligned} f(B(x)) &\equiv f(A(x)) + f'(A(x))(B(x) - A(x)) &\pmod {x^{2n}}\\ B(x) &\equiv A(x) - \frac{f(A(x))}{f'(A(x))} &\pmod {x^{2n}} \end{aligned} \]
大多數情況下,多項式複合是比較難求解的一個東西,但對於一些特殊的 \(f\) 可以方便求出。

多項式求逆

原理

好像這個不好套牛迭,我們現推算了。。

\(F(x)\)\(P(x)\)\(\pmod {x^n}\) 下的逆元,那麼表示出來就是
\[ F(x)P(x) \equiv 1 \pmod {x^n} \]
\(n = 1\) 求逆元即可,假設我們求出在 \(\bmod x^{\frac n 2}\) 意義下的逆元 \(G(x)\) ,那麼有
\[ G(x)P(x) \equiv 1 \pmod {x^\frac n 2}\\ \]
我們有
\[ \begin{aligned} F(x) - G(x) &\equiv 0 \pmod {x^\frac n 2}\\ F^2(x) - 2F(x)G(x) + G^2(x) &\equiv 0 \pmod {x^n}\\ F(x) &\equiv 2G(x) - P(x)G^2(x) \pmod {x^n} \end{aligned} \]
那麼遞歸求解即可,複雜度 \(\displaystyle \mathcal T(n) = \mathcal T(\frac n2) + \mathcal O(n \log n) = \mathcal O(n \log n)\)

實現

下面這種版本跑的有點慢,最好先 \(\text{NTT}\) 做點值乘法,能少一半常數。(注意一開始需要是 \(2^k \ge len\) 形式)

void Inv(int *f, int *g, int lf) {
    if (lf == 1) return void(g[0] = fpm(f[0], Mod - 2));
    Inv(f, g, lf >> 1); static int tmp[Maxn];
    Mult(f, g, tmp, lf, lf);
    Rep (i, lf) tmp[i] = (Mod - tmp[i]) % Mod; tmp[0] += 2;
    Mult(tmp, g, g, lf, lf);
}

多項式開根

原理

\(F^2(x) \equiv P(x) \pmod {x^n}\) ,此時的 \(f(A(x)) = A^2 - P\) 我們要求它的零點。

那麼我們套用牛迭的式子就得到了

\[ \begin{aligned} B(x) &= A(x) - \frac{A^2(x) - P(x)}{2A(x)}\\ &= \frac{A(x)}2 + \frac{P(x)}{2A(x)} \end{aligned} \]

複雜度 \(\displaystyle \mathcal T(n) = \mathcal T(\frac n2) + \mathcal O(n \log n) = \mathcal O(n \log n)\) 。 。。主定理是真的強大

實現

void Sqrt(int *f, int *g, int lf) {
    if (lf == 1) return void(g[0] = 1);
    Sqrt(f, g, lf >> 1); static int tmp[Maxn], tinv[Maxn];
    Rep (i, lf) tmp[i] = 2 * g[i] % Mod; Inv(tmp, tinv, lf);
    Mult(f, tinv, tmp, lf, lf);
    const int inv2 = fpm(2, Mod - 2);
    Rep (i, lf) g[i] = (1ll * g[i] * inv2 % Mod + tmp[i]) % Mod;
}

多項式ln

原理

\(F(x) = \ln G(x)\) ,我們有
\[ \ln G(x) = \int \frac{F'(x)}{F(x)} \mathrm{d}x \]
那麼我們求導然後再求逆即可,複雜度 \(\mathcal O(n \log n)\)

實現

void Ln(int *f, int *g, int lf) {
    static int der[Maxn], tmp[Maxn];
    Der(f, der, lf); Inv(f, tmp, lf);
    Mult(der, tmp, tmp, lf, lf); Int(tmp, g, lf);
}

多項式exp

原理

可以套用牛迭代和多項式 \(\ln\) 解決。

分治的做法雖然多了個 \(\mathcal O(\log)\) 但好寫許多(而且通常由於常數優勢會比較快,除非你會論文哥那個牛迭優化),原理如下
\[ \begin{aligned} B(x) &= \exp(A(x))\\ B'(x) &= A'(x) \exp(A(x))\\ B'(x) &= A'(x) B(x)\\ B(x) &= \int A'(x)B(x) \mathrm{d}x \end{aligned} \]

我們考慮把 \(A(x)\) 先求導成 \(A'(x)\) ,令 \(mid = \lfloor \frac{l + r}2 \rfloor\) 然後考慮分治求出 \([l, mid]\)\(B(x)\) ,然後考慮對於 \((mid, r]\) 的貢獻,也就是 \(A_{0 \sim r - l}\)\(B_{l \sim mid}\) 卷然後貢獻上去。

注意 \(A(0) = 0\) 纔在膜意義下有含義,此時 \(B(0) = 1\) ,以及積分需要平移一位並乘上 \(\frac{1}{n}\) 。複雜度 \(\mathcal O(n \log^2 n)\)

實現

void Exp(int *a, int *b, int l, int r) {
    if (l == r) return void(b[l] = (l ? 1ll * b[l] * inv[l] % Mod : 1));
    int mid = (l + r) >> 1;
    Exp(a, b, l, mid); static int tmp[Maxn];
    Mult(a, b + l, tmp, r - l, mid - l);
    For (i, mid + 1, r) b[i] = (b[i] + tmp[i - l - 1]) % Mod;
    Exp(a, b, mid + 1, r);
}

void Exp(int *f, int *g, int lf) {
    static int der[Maxn];
    Der(f, der, lf); der[lf] = 0;
    memset(g, 0, sizeof(int) * (lf + 1));
    Exp(der, g, 0, lf);
}

多項式複合逆

原理

\(G(F(x)) = x\) 此時 \(G(x)\) 可能是和 \(F\) 同階的一個多項式,套用牛頓迭代項數會特別多,根本無法求解。

但要求單項即 \([x^n]F(x)\) 有一個可以快速計算的式子
\[ [x^n] F(x) = \frac 1n [x^{n - 1}] (\frac{x}{G(x)})^n \]
至於證明可以參看這篇博客

最後解決多項式快速冪,我們用前面實現的 \(\ln\)\(\exp\) 就可以變成每項乘 \(n\) 了,\(\mathcal O(n \log n)\)

實現

int Lagrange(int *f, int lf, int x) {
    static int tmp[Maxn], res[Maxn];
    Rep (i, lf) tmp[i] = f[i + 1]; Inv(tmp, res, lf);
    Ln(res, tmp, lf); Rep (i, lf) tmp[i] = 1ll * tmp[i] * x % Mod; Exp(tmp, res, lf);
    return 1ll * res[x - 1] * fpm(x, Mod - 2) % Mod;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章