1. 前置知識
1.1 基礎
\(f(x) = \sum_{i=0}^na_ix^i\) 被稱為一個 \(n\) 次多項式。
\(\deg f(x)\) 表示多項式的次數。
\(f(x)g(x) = h(x)\) 稱為多項式乘法,也叫多項式卷積,滿足 \(h_n = \sum_{i + j = n}f_ig_j\)。
1.2 點值
給定一個多項式 \(f(x)\),再給 \(m\) 個點 \(x_1, \dots, x_m\),求 \(f(x_1), \dots, f(x_m)\)。
1.3 插值
1.3.1 定義
對於一個多項式 \(f(x)\),給定 \(n\) 橫座標不相同的個點 \((x_0, y_0), \dots, (x_{n - 1}, y_{n - 1})\), 求一個多項式 \(f(x)\) 使得對於所有 \(0 \le i < n\),\(f(x_i) = y_i\)。
不難證明如果 \(\deg f(x) < n\) 則 \(f(x)\) 是唯一的。
考慮反證法,存在 \(f(x)\) 和 \(g(x)\) 滿足要求。
則設 \(r(x) = f(x) - g(x)\),顯然 \(r(x)\) 有 \(n\) 個根。但是 \(\deg r(x) < n\),所以 \(r(x) = 0\),矛盾!
所以唯一性得證。
1.3.2 拉格朗日插值
Lagrange 插值法,是一種可以計算 \(f(x)\) 的各項係數的方法。
我們考慮構造 \(n\) 個多項式滿足 \(P_i(x_i) = y_i, P_i(x_j) = 0\),顯然答案就是 \(\sum P_i(x)\)。
不難得出:
則最終的答案:
這個用程式碼實現複雜度是 \(O(n^2)\) 的。
1.4 複數
1.4.1 定義
定義 \(i^2 = -1\),稱為虛數。
對於所有 \(a, b \in \mathbb{R}\) 的 \(z = a + bi\) 稱為複數。
1.4.2 基礎知識
複數可以用笛卡爾座標系來表示,橫座標表示實數,縱座標表示虛樹,\(a + bi\) 對應 \((a, b)\)。
一個複數可以對應到一個向量上。
不妨設 \(r = \sqrt{a^2 + b^2}\),\(\theta\) 為 \(\overrightarrow{z} = a + bi\) 的夾角,則我們也可以表示為:\(\overrightarrow{z} = r(\cos \theta + i \sin \theta)\)。
1.4.3 尤拉公式
證明可以用泰勒展開來證明。
1.4.4 單位根
在複數域上,方程 \(x^n = 1\) 會有 \(n\) 個不同的解,這 \(n\) 個不同的解記作 \(\varepsilon_n^0, \dots, \varepsilon_n^{n-1}\)。
根據尤拉公式,我們有:
這樣可以快速計算單位根。
畫在單位圓上,單位根會將整個單位圓 \(n\) 等分。
單位根有一些性質和定理:
折半定理: \(\varepsilon^2_{2n} = \varepsilon^1_{n}\)
2. 快速傅立葉變換 (FFT)
2.1 大致思路
考慮到多項式卷積的樸素演算法是 \(O(n^2)\) 的。我們需要最佳化到 \(O(n \log n)\)。
根本原理在於只需知道 \(n\) 個點就能確定 \(h(x)\),我們透過選取特殊的點來最佳化計算。
整個過程分為三步:
-
選取一些點 \(x_0, \dots, x_{n -1}\), 計算 \(f(x)\) 和 \(g(x)\) 的點值。
-
根據 \(h(x) = f(x)g(x)\) 計算出 \(h(x)\) 的點值。
-
插值得到 \(h(x)\)。
2.2 DFT 點值
我們考慮選取 \(n\) 次單位根 \(\varepsilon_n^0, \varepsilon_n^1, \dots, \varepsilon_n^{n-1}\) 作為點值。
考慮利用分治來求解。我們要求 \(n = 2^k\),如果不是就補齊即可。
不妨設 \(f(x) = \sum_{i = 0}^{n - 1}a_ix^i\),我們根據係數下標的奇偶性分開成兩個多項式:
不難發現 \(f(x) = f^{(0)}(x^2) + xf^{(1)}(x^2)\),我們將問題轉化成計算這兩個多項式在 \(\varepsilon_{\frac{n}{2}}^0, \dots, \varepsilon_{\frac{n}{2}}^{\frac{n}{2}-1}\) 的點值。
根據折半定理,\(\varepsilon_n^k = \varepsilon_\frac{n}{2}^{k \bmod \frac{n}{2}}\),所以我們可以透過這兩個多項式推出原來的多項式。
2.3 IDFT 插值
不妨考慮寫成矩陣的形式:
其中 \(V(i,j) = \epsilon_n^{ij \bmod n}\)。
則我們現在知道 \(V, Y\),需要求出 \(A\)。
我們只需要求出 \(V^{-1} . Y\) 即可。
根據觀察可以發現 \(V^{-1} = \frac{1}{n}\varepsilon_n^{-ij}\)。
所以我們就可以計算出係數了。