-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Fast Fourier Transform #68
Conversation
TimmyChiang
commented
May 14, 2023
•
edited
Loading
edited
- Read Contribute to NTHU-CPP.
- Rebase to the latest main branch.
- List all the references.
- Successfully build the website by mdBook with no error after the change.
- Exclude any irrelevant files.
- Link to the issue which is related to your change.
- Review the content by myself.
- Pass tests/CI.
I've turned this PR to draft PR. |
嗨~ 很抱歉沒有辦法把 issue 中的題目全部完成。目前只有將模板題和兩題基本的 string matching 題目放上去。 |
Please fix your commit history... |
c3eb136
to
7363867
Compare
Commit history fixed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, there's still lack of explanation. Please try to figure out how to make your article clear and easy for a CS major student at maybe 3rd grade.
src/SUMMARY.md
Outdated
@@ -25,6 +25,7 @@ | |||
- [杜教篩](math/du_sieve.md) | |||
- [Arithmetic Function Revisit](math/revisit_arithmetic_function.md) | |||
- [Miscellaneous]() | |||
- [Fast Fourier Transform](miscellaneous/fast_fourier_transform.md) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be under math
|
||
本單元介紹快速傅立葉轉換法 (Fast Fourier Transform, 簡稱 FFT ). FFT 是一個計算離散傅立葉轉換 (Discrete Fourier Transform, 簡稱 DFT ) 的演算法。此算法最經典的應用在計算多項式相乘,亦即給定兩個 \\( n \\) 次多項式,求兩多項式的乘積。直覺上有個 \\( O(n^2) \\) 的算法是將係數逐一相乘再相加,而 FFT 利用分治法提供一個 \\( O(n \log n) \\)的算法。為了討論方便,我們有以下假設: | ||
|
||
- 所有 \\( n \\) 皆為 \\( 2 \\) 的冪次方 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
這邊簡單提一下若不為 2的密次怎麼辦
或者說 你實作也是考慮 n 是 2 的密次嗎?
是的話實作部分也需要提
|
||
### \\( n \\) 次單位根 (The principal nth root of unity) | ||
|
||
給定方程式 \\( z^n = 1 \\), 其中 \\( n \\) 為正整數,\\( z \\) 為複數。我們稱 \\( z \\) 為該方程式的 \\( n \\) 次單位根。設 \\( \omega_n = e^{\frac{2 \pi i}{n}} \\), 該方程式的 \\( n \\) 次單位跟有 \\( n \\) 個,分別為 \\( \omega_n, \omega_n^2, \cdots, \omega_n^{n-1} \\) 和 \\( 1 \\). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
單位跟 -> 單位根
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
設 \( \omega_n = e^{\frac{2 \pi i}{n}} \), 該方程式的 \( n \) 次單位跟有 \( n \) 個,分別為 \( \omega_n, \omega_n^2, \cdots, \omega_n^{n-1} \) 和 \( 1 \).
這句看不懂需要多點解釋
|
||
$$ \left( \begin{matrix} 1 & \alpha_1 & \cdots & \alpha_1^{n-1} \\\ 1 & \alpha_2 & \cdots & \alpha_2^{n-1} \\\ \vdots & \vdots & \ddots & \vdots \\\ 1 & \alpha_m & \cdots & \alpha_m^{n-1} \end{matrix} \right)_{m \times n} $$ | ||
|
||
在 FFT algorithm 中,我們聚焦在以下這個特例:第 \\( i \\) 行和第 \\( i \\) 列的公比均為 \\( \omega_n^{i-1} \\) 且 \\( a_{11} \\) 為 \\( 1 \\) 的范德蒙方陣 \\( V \\) 上。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is a_{11}
\right)_{n \times n} | ||
$$ | ||
|
||
由於反矩陣若存在必為一。經過驗證可以得到 \\( V \\) 的反矩陣如下 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
為ㄧ->唯一
#### 計算方法 | ||
|
||
給定 \\( A(x) = a_0 + a_1 x + a_2 x^2 + \cdots + a_{n-1} x^{n-1} \\), 若將多項式次方為偶數的項總和 \\( a_0 + a_2 x^2 + \cdots + a_{n-2} x^{n-2} \\) 記作 \\( A^{[0]}(x) \\), 次方為奇數的項總和 \\( a_1 x + a_3 x^3 + \cdots + a_{n-1} x^{n-1} \\) 記作 \\( A^{[1]}(x) \\), 則 | ||
|
||
$$ | ||
A(x) = A^{[0]}(x^2) + xA^{[1]}(x^2) | ||
$$ | ||
|
||
觀察發現 \\( A^{[0]}(x) \\) 和 \\( A^{[1]}(x) \\) 的次方均為 \\( A(x) \\) 的一半。換言之,計算 \\( A(x) \\) 只需計算兩個次方為 \\( A(x) \\) 一半的值再相加即可。\\( y \\) 中的元素共有 \\( n \\) 個,表示我們要將 \\( n \\) 個 \\( x \\) 代入 \\( A(x) \\) 計算結果。若以 \\( T(n) \\) 代表計算 \\( n \\) 個 \\( x \\) 代入 \\( A(x) \\) 所需的計算時間,我們可以列出關係式 | ||
|
||
$$ | ||
T(n) = 2T\left(\frac{n}{2}\right) + O(n) | ||
$$ | ||
|
||
得總時間為 \\( O(n \log n) \\). 值得一提的是,這裡所有的變數 \\( x \\) 可以是任意複數。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
看不懂這是要計算什麼...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
以及那遞迴是怎麼來的
- Step 2: 利用前述計算 DFT 的方法,在 \\( O(n \log n) \\) 時間算出 | ||
$$ | ||
y_a = \left( A(1), A(\omega_{2n}), A(\omega_{2n}^2), \cdots, A(\omega_{2n}^{2n-1}) \right) | ||
$$ | ||
$$ | ||
y_b = \left( B(1), B(\omega_{2n}), B(\omega_{2n}^2), \cdots, B(\omega_{2n}^{2n-1}) \right) | ||
$$ | ||
|
||
- Step 3: 用 \\( O(n) \\) 時間算出 \\( C(x) \\) 的點值表示式 | ||
|
||
$$ | ||
y_c = \left( A(1)B(1), A(\omega_{2n})B(\omega_{2n}), A(\omega_{2n}^2)B(\omega_{2n}^2), \cdots, A(\omega_{2n}^{2n-1})B(\omega_{2n}^{2n-1}) \right) | ||
$$ | ||
|
||
- Step 4: 將 \\( C(x) \\) 的點值表示式轉換成係數表示式 | ||
|
||
$$ | ||
c = (c_0, c_1, c_2, \cdots, c_{2n}) | ||
$$ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
到這邊我才看懂
我覺得前面就可以依邊 hint 讀者 FFT 大概是要怎麼做的
例如前面介紹點值表示是時就可以hint 讀者既然換成點值可以 O(n) 那 FFT 其中一部就是要換成點值之類的
$$ | ||
\left( | ||
\begin{matrix} | ||
y_0 \\\\ | ||
y_1 \\\\ | ||
y_2 \\\\ | ||
\vdots \\\\ | ||
y_{2n} | ||
\end{matrix} | ||
\right) | ||
= | ||
\left( | ||
\begin{matrix} | ||
1 & 1 & 1 & \cdots & 1 \\\\ | ||
1 & \omega_{2n} & \omega_{2n}^2 & \cdots & \omega^{2n-1} \\\\ | ||
1 & \omega_{2n}^2 & \omega_{2n}^4 & \cdots & \omega^{2(2n-1)} \\\\ | ||
\vdots & \vdots & \vdots & \ddots & \vdots \\\\ | ||
1 & \omega_{2n}^{2n-1} & \omega_{2n}^{2(2n-1)} & \cdots & \omega_n^{(2n-1)(2n-1)} | ||
\end{matrix} | ||
\right) | ||
\left( | ||
\begin{matrix} | ||
a_0 \\\\ | ||
a_1 \\\\ | ||
a_2 \\\\ | ||
\vdots \\\\ | ||
a_{2n} | ||
\end{matrix} | ||
\right) | ||
$$ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
你前面那麼早就介紹這個矩陣
讀者到這邊反而會ㄇㄤ 掉?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
當初想說把背景知識(工具)一口氣講完後再講怎麼去使用。目前想到兩個解決方法,第一個是直接把范德蒙矩陣從背景知識拿掉,到這邊再拉出來介紹。另一個是背景知識的部分不動,這邊再做回顧就好。你覺得哪個可能比較適合,或是有沒有其他解決方法~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
我沒什麼想法
你可以多參考其他你覺得寫得不錯的人的做法
|
||
## 模板與習題 | ||
|
||
### 模板 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you have to describe the use of double and long long, would it cost floating point error and so on.
### 模板題 | ||
|
||
> [SPOJ - Polynomial Multiplication](https://www.spoj.com/problems/POLYMUL/) | ||
> | ||
> 給定兩個 \\( n \\) 次多項式的係數,輸出兩個多項式相乘的多項式係數。 | ||
|
||
<details><summary>Solution</summary> | ||
|
||
讀取輸入資料後,直接呼叫 ```multipy()``` 即可。 | ||
|
||
</details> | ||
|
||
### 基礎題 | ||
|
||
> [SPOJ - Maximum Self-Matching](https://www.spoj.com/problems/MAXMATCH/) | ||
> | ||
> 給定一個只包含 ```a```, ```b``` 和 ```c``` 的字串 ```str```. 定義 \\( m_{str}(i) \\) 為字串 ```str``` 向右移動 \\( i \\) 個字元後與自己匹配的字元個數。求最大的 \\( m_{str}(i) \\) 值以及所有讓 \\( m_{str}(i) \\) 最大的 \\( i \\). | ||
|
||
<details><summary>Solution</summary> | ||
|
||
設輸入字串 ```str``` 長度為 \\( n \\). 令字串 ```t``` 為將字串中為 ```a``` 的位置設為 ```1```, 其他設為 ```0``` 的字串。構造一個與 ```t``` 對應的多項式 \\( p_t \\)。例如 ```baaca``` 經構造會得到 ```01101```, 對應的多項式為 \\( x^3 + x^2 + 1 \\). ```acaa``` 經構造會得到 ```1011```, 對應的多項式為 \\( x^3 + x + 1 \\). 令 ```r``` 為 ```t``` 的反轉字串,我們同樣地對 ```r``` 構造一個對應的多項式 \\( p_r \\). | ||
|
||
將 \\( p_t \\) 和 \\( p_r \\) 相乘得到的多項式,其係數即為右移次方數減 \\( n \\) 個字元的成功匹配數。故只需針對 ```a```, ```b``` 和 ```c``` 各做一次 FFT 後再將係數相加取最大值,即為所求。 | ||
|
||
</details> | ||
|
||
> [SPOJ - Ada and Nucleobase](https://www.spoj.com/problems/ADAMATCH/) | ||
> | ||
> 給定兩個 DNA 序列 ```s``` 和 ```r```, 其中 ```r``` 的長度比 ```s``` 短。輸出 ```r``` 與 ```s``` 中所有連續子字串的 hamming distance 最小值。 | ||
|
||
<details><summary>Solution</summary> | ||
|
||
本題與前一題 [SPOJ - Maximum Self-Matching](https://www.spoj.com/problems/MAXMATCH/) 類似。差異處只有兩點,第一是 ```a```, ```b```, 和 ```c``` 變成 ```A```, ```T```, ```C```, 和 ```G```. 第二是 hamming distance 即自己字串的長度扣掉匹配數。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If possible, please use CSES, CF, Atcoder as the source of the problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be two section:
- Example problem, you have to explain the problem in detail.
- Excercise problem, the problem list for reader to exercise.
For example: https://nthu-cp.github.io/NTHU-CPP/sqrt/sqrt_decomposition.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also for some problem, it would be great to see the AC code that use the template code you provide.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I believe there's a lot of cool application for FFT, please include more interesting problem.
friendly ping |
Got it. Thanks! |
7363867
to
d1b6255
Compare