多項式基本操作

多項式求逆

給定一個 \(n-1\) 次的多項式 \(A(x)(a_0 \neq 0)\) ,要求一個多項式 \(F(x)\) 滿足 \(F(x)A(x) \equiv 1 \pmod x^n\)
假設求出了 \(F_0(x)\) 滿足 \(F_0(x)A(x) \equiv 1 \pmod{x^{\lceil \frac{n}{2} \rceil}}\) ,那麼有

\[\begin{aligned} F_0(x)A(x) \equiv F(x)A(x) \equiv 1 \pmod{x^{\lceil \frac{n}{2} \rceil}} \\A(x)(F(x)-F_0(x)) \equiv 0 \pmod{x^{\lceil \frac{n}{2} \rceil}} \end{aligned} \]

由於 \(A(x) \neq 0\) ,所以

\[\begin{aligned} F(x)-F_0(x) \equiv 0 \pmod{x^{\lceil \frac{n}{2} \rceil}} \\(F(x)-F_0(x))^2 \equiv 0 \pmod{x^n} \\F^2(x)-2F(x)F_0(x)+F_0^2(x) \equiv 0 \pmod{x^n} \end{aligned} \]

又因爲 \(F(x)A(x) \equiv 1 \pmod{x^n}\) ,兩邊都乘個 \(A(x)\)

\[F(x) \equiv 2F_0(x)-A(x)F_0^2(x) \pmod{x^n} \\ \equiv F_0(x)(2-A(x)F_0(x)) \pmod{x^n} \]

所以我們可以遞歸求解,時間複雜度 \(T(n) = T(n/2)+n\log n = n\log n\)

void get_inv(int *a, int *f, int n){
	if(n == 1)return f[0] = fpow(a[0], mod-2), void();
	get_inv(a, f, n+1>>1), init(2*n-1);//init()處理數組長度和蝴蝶變換
	fp(i, 0, n-1)inv_ary[i] = a[i];
	ntt(f, 0), ntt(inv_ary, 0);
	fp(i, 0, lim-1)f[i] = 1ll*f[i]*(2-1ll*f[i]*inv_ary[i]%mod+mod)%mod;
	ntt(f, 1);
	fp(i, n, lim-1)f[i] = 0;
	fp(i, 0, lim-1)inv_ary[i] = 0;
}

多項式求 \(\rm{ln}\)

給定一個 \(n-1\) 次的多項式 \(A(x)(a_0 = 1)\) ,要求一個多項式 \(F(x)\) 滿足 \(F(x) \equiv \ln A(x) \pmod{x^n}\)
兩邊求個導得到:

\[F'(x) \equiv \frac{A'(x)}{A(x)} \pmod{x^n} \]

所以只需要對 \(A(x)\) 求個導和逆就能求出 \(F'(x)\) 了。最後再對 \(F'(x)\) 求個積分,由於 \(a_0=1\) ,所以常數項爲 \(0\) 。時間複雜度爲 \(\mathcal{O} (n\log n)\)

void get_ln(int *a, int *f, int n){
	get_inv(a, ln_ary, n), init(2*n-2);
	fp(i, 1, n-1)f[i-1] = 1ll*a[i]*i%mod;
	ntt(f, 0), ntt(ln_ary, 0);
	fp(i, 0, lim-1)f[i] = 1ll*f[i]*ln_ary[i]%mod;
	ntt(f, 1);
	fp(i, n-1, lim)f[i] = 0;
	fp(i, 0, lim)ln_ary[i] = 0;
	fb(i, n-1, 1)f[i] = 1ll*f[i-1]*inv[i]%mod;
	f[0] = 0;
}

牛頓迭代

給定一個函數 \(G(x)\) ,要求一個多項式 \(F(x)\) 滿足 \(G(F(x)) \equiv 0 \pmod{x^n}\)
假設求出了 \(F_0(x)\) 滿足 \(G(F_0(x)) \equiv 0 \pmod{x^{\lceil \frac{n}{2}\rceil}}\) ,那麼把 \(G(x)\)\(F_0(x)\) 處泰勒展開可以得到:

\[G(F(x)) \equiv G(F_0(x))+G'(F_0(x))(F(x)-F_0(x))+\frac{G''(F_0(x))}{2}(F(x)-F_0(x))^2+\cdots \pmod{x^n} \\ \equiv G(F_0(x))+G'(F_0(x))(F(x)-F_0(x)) \equiv 0 \pmod{x^n} \\ F(x) \equiv F_0(x)-\frac{G(F_0(x)}{G'(F_0(x))} \pmod{x^n} \]

因爲 \(F(x)-F_0(x)\) 最低次是 \(x^{\lceil \frac{n}{2}\rceil}\) ,所以從第三項開始模 \(x^n\) 就爲 \(0\) 了。 注意這裏的求導是求 \(F_0(x)\) 的偏導 。然後就可以遞歸計算了。


多項式 \(\rm{exp}\)

給定一個 \(n-1\) 次多項式 \(A(x)(a_0=0)\) ,要求一個多項式 \(F(x)\) 滿足 \(F(x) \equiv e^{A(x)} \pmod{x^n}\)
兩邊求個 \(\ln\)\(\ln F(x) \equiv A(x) \pmod{x^n}\) 。設 \(G(F(x))=\ln F(x)-A(x)\) ,那就相當於求 \(F(x)\) 滿足 \(G(F(x)) \equiv 0 \pmod{x^n}\)
根據牛頓迭代的式子, \(F(x) \equiv F_0(x)-F_0(x)(\ln F_0(x)-A(x)) \equiv F_0(x)(1-\ln F_0(x)+A(x))\) 。遞歸求解即可,時間複雜度 \(\mathcal{O} (n\log n)\)

void get_exp(int *a, int *f, int n){
	if(n == 1)return f[0] = 1, void();
	get_exp(a, f, n+1>>1), get_ln(f, exp_ary, n), init(2*n-1);
	fp(i, 0, n-1)exp_ary[i] = (a[i]-exp_ary[i]+mod)%mod;
	if((++exp_ary[0]) ==  mod)exp_ary[0] = 0;
	ntt(f, 0), ntt(exp_ary, 0);
	fp(i, 0, lim-1)f[i] = 1ll*f[i]*exp_ary[i]%mod;
	ntt(f, 1);
	fp(i, n, lim-1)f[i] = 0;
	fp(i, 0, lim-1)exp_ary[i] = 0;
}

分治 \(\rm{FFT/NTT}\)

求出 \(\prod_{i=1}^n(a_{i,0}+a_{i,1}x+a_{i,2}x^2+ \cdots +a_{i,k+1}x^{k+1})\) ,要求複雜度爲 \(\mathcal{O} (nk \log^2 nk)\) 。一般情況下 \(k\) 都等於 \(1\)
顯然不能從左到右乘過去,這樣的話複雜度高達 \(\mathcal{O} (n^2)\)
考慮分治,每次做完左右兩邊的乘法,這樣左右兩邊的長度都是 \(\frac{len}{2}\) 的, \(len\) 是當前的分治區間長度。然後把兩邊的乘起來即可。顯然複雜度降到了 \(\mathcal{O} (nk \log^2 nk)\) 。當 \(k=1\) 時就是 \(\mathcal{O} (n \log^2 n)\)
貼個 \(k=1\) 時的代碼(\(a_0 = 1\))。

int div_ary[20][maxn<<2];
void divntt(int d, int l, int r){
	if(l == r)return div_ary[d][0] = 1, div_ary[d][1] = mod-a[l], void();
	int md = l+r>>1, len = r-l+2;
	divntt(d, l, md), divntt(d+1, md+1, r), init(len), ntt(div_ary[d], 0), ntt(div_ary[d+1], 0);
	fp(i, 0, lim-1)div_ary[d][i] = 1ll*div_ary[d][i]*div_ary[d+1][i]%mod;
	ntt(div_ary[d], 1);
	fp(i, len, lim-1)div_ary[d][i] = 0;
	fp(i, 0, lim-1)div_ary[d+1][i] = 0;
}

常見的數

第一類斯特林數

定義\(\begin{bmatrix} n\\m \end{bmatrix}\) 表示把 \(n\) 個有標號元素劃分成 \(m\) 個圓排列的方案數。
遞推公式

\[\begin{aligned} \begin{bmatrix} n\\m \end{bmatrix} = \begin{bmatrix} n-1\\m-1 \end{bmatrix}+(n-1)\begin{bmatrix} n-1\\m \end{bmatrix} \quad (n > 1) \\\begin{bmatrix} n\\0 \end{bmatrix} = [n=0] \\\begin{bmatrix} n\\1 \end{bmatrix} = (n-1)! \quad (n \geq 1) \end{aligned} \]

考慮加入第 \(n\) 個元素,它要麼新成一個環,要麼排在前 \(n-1\) 個元素中某一個的後面。
組合意義\(n! = \sum_{i=0}^n\begin{bmatrix} n\\i \end{bmatrix}\)
可以理解爲一個排列對應爲若干個置換,每個置換又對應一個圓排列。
生成函數\(\sum_{i=0}^{\infty} \begin{bmatrix} n\\i \end{bmatrix}x^i=x^{\overline{n}}\)
考慮歸納法,首先有 \(\begin{bmatrix} 0\\0 \end{bmatrix}x^0=x^{\overline{0}}\)

\[(x+n)x^{\overline{n}} = x^{\overline{n+1}} \\(x+n)\sum_{i=0}^{\infty} \begin{bmatrix} n\\i \end{bmatrix}x^i = n!x+\sum_{i=2}^{\infty}(\begin{bmatrix} n-1\\i-1 \end{bmatrix}+\begin{bmatrix} n-1\\i \end{bmatrix})x^i=\sum_{i=0}^{\infty} \begin{bmatrix} n+1\\i \end{bmatrix}x^i \]

所以 \(\sum_{i=0}^{\infty} \begin{bmatrix} n+1\\i \end{bmatrix}x^i=x^{\overline{n+1}}\)
考慮求這個生成函數。直接的方法可以用分治 \(\rm{NTT}\) 求,複雜度 \(\mathcal{O} (n\log^2 n)\)。還有種倍增的方法。
\(F_n(x) = x^{\overline{n}}\) ,考慮怎麼通過它求出 \(F_{2n}(x)\) 。顯然有 \(F_{2n}=F_n(x)F_n(x+n)\)

\[\begin{aligned} F_n(x+n) = \sum_{i=0}^{\infty} \begin{bmatrix} n\\i \end{bmatrix}(x+n)^i \\=\sum_{i=0}^n \begin{bmatrix} n\\i \end{bmatrix}\sum_{j=0}^i{i\choose j}n^{i-j}x^j \\=\sum_{j=0}^nx^j\sum_{i=j}^n {i \choose j}\begin{bmatrix} n\\i \end{bmatrix}n^{i-j} \\=\sum_{j=0}^n\frac{x^j}{j!}\sum_{i=j}^n\frac{i!}{(i-j)!}\begin{bmatrix} n\\i \end{bmatrix}n^{i-j} \end{aligned} \]

很容易看出來後面的式子可以卷積。設 \(a_i=i!\begin{bmatrix} n\\i \end{bmatrix},b_i=\frac{n^i}{i!}\),將 \(a\) 的下標反轉一下,卷積的第 \(n-j\) 次項係數除以 \(j!\) 就是 \(F_n(x+n)\) 的第 \(j\) 次項係數。現在就可以遞歸求解了,當 \(n\) 爲奇數時就將 \(n\) 減一,求出多項式後乘一個 \(x+n-1\) 即可。複雜度 \(\mathcal{O} (n\log n)\)


第二類斯特林數

定義\(\begin{Bmatrix} n\\m \end{Bmatrix}\) 表示將 \(n\) 個有標號元素劃分爲 \(m\) 個無標號非空集的方案數。
遞推公式

\[\begin{aligned} \begin{Bmatrix} n\\m \end{Bmatrix} = \begin{Bmatrix} n-1\\m-1 \end{Bmatrix}+m\begin{Bmatrix} n-1\\m \end{Bmatrix} \\\begin{Bmatrix} n\\0 \end{Bmatrix} = [n = 0] \end{aligned} \]

考慮加入第 \(n\) 個元素,它要麼新成一個集合,要麼被划進已有的元素。
組合意義\(m^n = \sum_{i=0}^m{m\choose i}\begin{Bmatrix} n\\i \end{Bmatrix}i!\)
因爲左邊是 \(n\) 個有標號元素劃分爲任意個有標號集合的方案數,那麼枚舉有幾個非空集,很自然能得到右邊的式子。
通項公式

\[\begin{Bmatrix} n\\m \end{Bmatrix} = \frac{1}{m!}\sum_{i=0}^m(-1)^i{m \choose i}(m-i)^n \]

有兩種方法理解這個式子:
由於不能選空集,那就容斥掉空集的情況。所以枚舉選了 \(i\) 個空集,然後將所有 \(n\) 個元素放入 \(m-i\) 個集合中(可以爲空集)。容易看出來容斥係數爲 \((-1)^i{m\choose i}\)
或者考慮二項式反演:

\[m^n = \sum_{i=0}^m{m\choose i}\begin{Bmatrix} n\\i \end{Bmatrix}i! \\\begin{Bmatrix} n\\m \end{Bmatrix}m! = \sum_{i=0}^m(-1)^i{m \choose i}(m-i)^n \]

有了這個通項之後就可以 \(\mathcal{O} (n\log n)\) 求解一行第二類斯特林數了,因爲把組合數打開可以發現是卷積的形式。


貝爾數

定義\(B_n\) 表示將 \(n\) 個有標號元素劃分爲任意個無標號非空集合的方案數。
遞推公式

\[\begin{aligned} B_{n+1} = \sum_{i=0}^n{n\choose i}B_{n-i} \\B_0 = 1 \end{aligned} \]

考慮加入第 \(n+1\) 個元素,枚舉它與多少個元素划進同一個集合,剩下的元素任意劃分。
組合意義

\[\begin{aligned} B_n = \sum_{i=0}^n\begin{Bmatrix} n \\ i \end{Bmatrix}=\sum_{m=0}^n\frac{1}{m!}\sum_{i=0}^m(-1)^{i}{m\choose i}(m-i)^n\\ =\sum_{m=0}^n\sum_{i=0}^m\frac{(-1)^{i}}{i!}\times \frac{(m-i)^n}{(m-i)!}\\ =\sum_{m=0}^n\sum_{i=0}^m\frac{(-1)^{m-i}}{(m-i)!}\times \frac{i^n}{i!}\\ =\sum_{i=0}^n\frac{i^n}{i!}\sum_{m=i}^n\frac{(-1)^{m-i}}{(m-i)!}\\ =\sum_{i=0}^n\frac{i^n}{i!}\sum_{m=0}^{n-i}\frac{(-1)^m}{m!} \end{aligned} \]

這樣的話後面的 \(\sum\) 就只與上界有關了,先給後面的 \(\sum\) 求個前綴和,再線篩 \(i^n\) ,就可以 \(\mathcal{O}(n)\) 求解一個貝爾數了。
生成函數\(\sum_{n=0}^{\infty}B_nx^n = e^{e^x-1}\)
寫出 \(n\) 個數劃分成一個集合的方案數 \(f_n\) ,顯然 \(f_n=1\) 。考慮劃分成任意個集合的方案數就是 \(e^{F(x)}\) ,其中 \(F(x) = \sum_{n=1}^{\infty}\frac{f_n}{n!}x^n = e^x-1\) 。所以寫一個多項式 \(\rm{exp}\) 就可以 \(\mathcal{O} (n\log n)\) 求解前 \(n\) 個貝爾數了。
通項公式

\[\begin{aligned} e^{e^x-1} = \frac{1}{e}e^{e^x}=\frac{1}{e}\sum_{n=0}^{\infty}\frac{(e^x)^n}{n!} \\=\frac{1}{e}\sum_{n=0}^{\infty}\frac{1}{n!}\sum_{i=0}^{\infty}\frac{(nx)^{i}}{i!} \\=\sum_{i=0}^{\infty}\frac{x^i}{i!}\times \frac{1}{e}\sum_{n=0}^{\infty}\frac{n^i}{n!} \end{aligned} \]

所以通項爲 \(\frac{1}{e}\sum_{n=0}^{\infty}\frac{n^i}{n!}\)
\(\rm Touchard\) 同餘
\(B_{n+p}\equiv B_n+B_{n+1}\pmod{p}\)
引理 \(1\)\(B_{n+m}=\sum_{i=0}^n\sum_{j=0}^m j^{n-i}\begin{Bmatrix}m\\j\end{Bmatrix}{n\choose i}B_i\)
把n+m個元素分成n個元素和m個元素。首先枚舉m個元素劃分成了j個集合,就有了\(\begin{Bmatrix}m\\j\end{Bmatrix}\);再枚舉n個元素中選i個出來任意劃分,就有了\({n\choose i}B_i\);再把剩下的n-i個元素隨意放進m個元素的那j個集合裏,就有了\(j^{n-i}\) 。根據乘法原理乘起來,就是\(B_{n+m}\)。正確性是因爲每種劃分方案都可以像這樣描述。
引理 \(2\)\(\begin{Bmatrix}n\\m\end{Bmatrix}\equiv0\pmod n(1<m<n),n\)爲質數 。
展開左邊的式子:\(\begin{Bmatrix}n\\m\end{Bmatrix}=\frac{1}{m!}\sum_{i=0}^m(-1)^i{m\choose i}(m-i)^n\),可以發現組合數的m!可以跟前面約了:

\[=\sum_{i=0}^m\frac{(-1)^i}{i!}\frac{(m-i)^n}{(m-i)!} \]

根據費馬小定理,可以把m-i的指數消一下:\(\equiv\sum_{i=0}^m\frac{(-1)^i}{i!}\frac{m-i}{(m-i)!}\pmod n\)

\[\equiv\sum_{i=0}^m\frac{(-1)^i}{i!}\frac{1}{(m-i-1)!}\pmod n\\ \equiv\frac{1}{(m-1)!}\sum_{i=0}^m{m-1\choose i}(-1)^i\pmod n \]

\(i=m\)的時候後面就=0,所以\(i\)最多等於\(m-1\),那麼根據二項式定理就可得:

\[\equiv[m-1=0]\pmod n \]

所以當\(1<m<n\)的時候\(\begin{Bmatrix}n\\m\end{Bmatrix}\)就同餘0。
證明 \(\rm Touchard\) 同餘:
最後我們寫出引理1的式子:

\[B_{n+p}=\sum_{i=0}^n\sum_{j=0}^p j^{n-i}\begin{Bmatrix}p\\j\end{Bmatrix}{n\choose i}B_i \\=\sum_{j=0}^p\begin{Bmatrix}p\\j\end{Bmatrix} \sum_{i=0}^nj^{n-i}{n\choose i}B_i \]

根據引理\(2\),當\(1<j<p\)時,後邊的式子值爲\(0\)。又根據第二類斯特林數的定義,當\(j=0\)時,後邊也爲\(0\),當\(j=1\)或者\(p\)時,\(\begin{Bmatrix}p\\j\end{Bmatrix}=1\),。所以這個式子可以進一步寫成:

\[\begin{Bmatrix}p\\1\end{Bmatrix}\sum_{i=0}^n{n\choose i}B_i+ \begin{Bmatrix}p\\p\end{Bmatrix}\sum_{i=0}^np^{n-i}{n\choose i}B_i \\=\sum_{i=0}^n{n\choose i}B_i+\sum_{i=0}^np^{n-i}{n\choose i}B_i \]

根據最開始的\(n^2\)的遞推式,加號左邊的就是\(B_{n+1}\);由於是模意義下的,所以當\(i\neq n\)時,\(p^{n-i}{n\choose i}B_i\equiv 0\pmod{p}\)。。當i=n時,這個式子等於\(B_n\)
所以\(B_{n+p}\equiv B_n+B_{n+1}\pmod{p}\)


劃分數

定義\(p_{n,m}\) 表示將 \(n\) 劃分成 \(m\) 個無標號 自然數 和的方案數。
遞推公式\(p_{n,m} = p_{n-m,m}+p_{n,m-1}\)
要麼給已有的 \(m\) 個數都加 \(1\) ,要麼加入一個 \(0\)
生成函數\(P_n(x) = \sum_{i=0}^{\infty}p_{i,n}x^i\)
根據遞推公式,

\[P_n(x) = \sum_{i=n}^{\infty}(p_{i-n,n}+p_{i,n-1})x^i=x^nP_n(x)+P_{n-1}(x) \\P_n(x) = \frac{P_{n-1}(x)}{1-x^n} \]

又有 \(P_1(x) = \sum_{i=0}^{\infty}x^i=\frac{1}{1-x}\) ,不難發現

\[P_n(x) = \prod_{i=1}^n\frac{1}{1-x^i} \]

直接的方法就是分治 \(\rm NTT\) ,複雜度 \(\mathcal{O} (n\log^2 n)\)
觀察到 \(x^i\) 的係數都是 \(-1\) ,考慮繼續優化:

\[\ln P_n(x) = -\sum_{i=1}^n\ln(1-x^i) \]

\(F_i(x) = \ln(1-x^i)\)

\[F_i'(x) = -\frac{ix^{i-1}}{1-x^i} = (-ix^{i-1})\sum_{j=0}^{\infty}x^{ij} \\F_i'(x) = -\sum_{j=0}^{\infty}ix^{i(j+1)-1}=-\sum_{j=1}^{\infty}ix^{ij-1} \\F_i(x) = -\sum_{j=1}^{\infty}\frac{x^{ij}}{j} \]

所以暴力確定 \(\ln P_n(x)\) 的係數是 \(\mathcal{O} (n\ln n)\) 的,再做個 \(\rm exp\) 就可以求得 \(P_n(x)\)


一些奇技淫巧

\(\rm EularTransform\)

給定長度爲 \(n\) 的數列 \(a\) ,要求 \(F(x) = \sum_{i=1}^n\frac{1}{1-a_ix}\)
當然可以通分+分治 \(\rm NTT\) ,但那樣常數有點大。
\(\rm EularTransform\) 的思想是通過 \(1-x(\ln (1-a_ix))' = 1+\frac{a_i}{1-a_ix}=\frac{1}{1-a_ix}\) ,得到

\[F(x) = n-x\sum_{i=1}^n(\ln(1-a_ix))'=n-x(\ln \prod_{i=1}^n(1-a_ix))' \]

\(\prod\) 就用分治 \(\rm NTT\) 算,複雜度 \(\mathcal{O} (n\log^2 n)\)

不知道叫啥

給定長度爲 \(n\) 的數列 \(a\) 和多項式 \(F(x)\) ,要求 \(\sum_{i=1}^nF(a_ix)\)
暴力做顯然是 \(\mathcal{O} (n^2)\) 的。
注意到最後的多項式的第 \(m\) 次項係數肯定是 \(\sum_{i=1}^na_i^m\) 。考慮寫出這玩意兒的 \(\rm OGF\)

\[G(x) = \sum_{m=0}^{\infty}(\sum_{i=1}^na_i^m)x^m= \sum_{i=1}^n\sum_{m=0}^{\infty}(a_ix)^m= \sum_{i=1}^n\frac{1}{1-a_ix} \]

剩下的就是上面的 \(\rm EularTransform\) 了。

自然數冪和

對於所有 \(n\in [0,N]\) 求出 \(\sum_{i=0}^mi^n\) ,也就是剛纔那個東西的特殊形式。
這次我們寫出 \(\rm EGF\)

\[F(x) = \sum_{n=0}^{\infty}(\sum_{i=0}^mi^n)\frac{x^n}{n!}=\sum_{i=0}^m\sum_{n=0}^{\infty}\frac{(ix)^n}{n!}=\sum_{i=0}^me^{ix}=\frac{e^{(m+1)x}-1}{e^x-1} \]

給分母展開求個逆再乘上分母即可。注意到分母的常數項爲 \(0\) 不能直接求逆,但是分子的常數項也爲 \(0\) ,同時除以 \(x\) 即可。複雜度 \(\mathcal{O} (n\log n)\)

任意模數 \(\rm NTT\)

\(A(x)B(x)\) 的係數對\(10^9+7\) 取模的結果,最高次項是 \(10^5\) 級別,係數是 \(10^9\) 級別。
分析可得最後係數的值域應是 \(10^23\) 以內。那麼對 \(998244353,1004535809,469762049\) 三個模數分別做 \(\rm NTT\) ,就能用 \(\rm CRT\) 解出真實值(因爲三個模數乘起來大於 \(10^23\) ),再對 \(10^9+7\) 取模即可。選這三個因爲原根都是 \(3\)


咕咕咕

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章