學習筆記 FFT

2022-09-14 17:24:10 字數 4203 閱讀 8071

複數

重要性質:複數相乘,輻角相加,模長相乘。

即 \(\operatorname(z_1\times z_2)=\operatorname(z_1)+\operatorname(z_2)\)。

那麼 \(\operatorname(z^n)=n\operatorname(z)\)。

弧度制三角函式

\(n\) 次冪 為 \(1\) 的複數叫做 \(n\) 次單位根,即方程 \(z^n=1\) 的複數根。\(n\) 次單位根有 \(n\) 個。

因為 \(z^n=1\),所以 \(\left\vert z\right\vert^n=1\)。而模長一定是個非負實數,所以 \(\left\vert z\right\vert=1\)。也就是說單位根到原點的距離為 \(1\),一定在單位圓(以原點為圓心,半徑為 \(1\) 單位長度的圓)上。

我們把所有 \(n\) 次單位根從 \(1\) 開始,沿逆時針方向記為 \(\omega_n^0,\omega_n^1,\dots\omega_n^\)。

由原方程還可以得到 \(\operatorname((\omega_n^k)^n)=n\operatorname(\omega_n^k)=\operatorname(1)\),所以把 \(1\) 逆時針旋轉 \(n\) 次,每次旋轉 \(\operatorname(\omega_n^k)\),結果還是 \(1\)。那麼 \(2\pi\mid n\operatorname(\omega_n^k)\)。每個單位根又互不相同,所以 \(\operatorname(\omega_n^k)=\dfrac2\pi\)。它們把單位圓 \(n\) 等分。\(\omega_n^k\) 相當於繞原點把 \(\omega_n^\) 逆時針旋轉 \(\dfrac\)。

對於 \(k~(k\ge n)\),定義 \(\omega_n^k=\omega_n^\)

性質:\(\omega_n^k=(\omega_n^1)^k\)

\(\omega_^=\omega_n^k\)

因為它們模長都是 \(1\),輻角也相等。

\(\omega_n^i\times\omega_n^j=\omega_n^\)

用性質 1 容易得證。

若 \(n\) 是偶數,\(\omega_n^}=-\omega_n^k\)

\(\omega_n^}=\omega_n^k\times\omega_n^\frac\),\(\operatorname(\omega_n^\frac)=180^\circ\),相當於把 \(\omega_n^k\) 繞原點旋轉 \(180^\circ\),即關於原點中心對稱,實部虛部都取相反數,所以是 \(-\omega_n^k\)。

\(\sum\limits_^\omega_n^i=\dfrac\times\omega_n^1-\omega_n^0}=0\)

(等比數列求和)

\(n+1\) 個點確定唯一 \(n\) 次多項式。我們可以用 \(n+1\) 個點表示原多項式,並對點值序列進行一些操作(如乘法),最後由這個點值序列得到乙個新的多項式,來代替原多項式之間的操作。

比如 \(f(x)=x^2+2x-1,g(x)=-3x+1\)

在 \(f(x)\) 上取 \((-1,-2)(0,-1)(1,2)(2,7)\)

在 \(g(x)\) 上取 \((-1,4)(0,1)(1,-2)(2,-5)\)

兩個點值序列中,橫座標相同的點的縱座標相乘,得到 \((-1,-8)(0,-1)(1,-4)(2,-35)\)

根據這些點確定乙個 \(3\) 次多項式得到 \(-3x^3-5x^2+5x-1\),恰好等於 \(f(x)\cdot g(x)\)。

dft 是把係數表達轉換成點值表達的過程。我們把單位根代入多項式得到點值序列。

考慮乙個 \(n-1\) 次(\(n\) 項)多項式 \(f(x)=\sum\limits_^f_ix^i\)。

由於 \(n\) 是 \(2\) 的整數冪時比較好做,故 \(n\) 不是 \(2\) 的整數冪時往高次項補 \(0\)。

把它按次數的奇偶性分類:

\(f(x)=f_0+f_2x^2+\dots+f_x^+f_1x+f_3x^3+\dots+f_x^\)

令 \(fl(x)=f_0+f_2x+f_4x^2+\dots+f_x^,fr(x)=f_1+f_3x+f_5x^2+\dots+f_x^\)

則有 \(f(x)=fl(x^2)+xfr(x^2)\)。

現要把單位根代入 \(f\)。

列舉 \(k~(0\le k<\dfrac)\)

\(f(\omega_n^k)=fl((\omega_n^k)^2)+\omega_n^kfr((\omega_n^k)^2)=fl(\omega_^k)+\omega_n^kfr(\omega_^k)\)

\(f(\omega_n^)=fl((\omega_n^)^2)+\omega_n^fr((\omega_n^)^2)=fl(\omega_n^)+\omega_n^fr(\omega_n^)=fl(\omega_^k)-\omega_n^kfr(\omega_^k)\)

如果我們知道了 \(x=\omega_^k~(0\le k時 \(fl(x)\) 和 \(fr(x)\) 的值,就可以算出 \(x=\omega_n^k~(0\le k時 \(f(x)\) 的值。\(fl,fr\) 可以遞迴求。

求單位根:用三角函式求出 \(\omega_n^1\),利用性質 1 每次乘上它,防止多次呼叫三角函式。

\(\large\\\large^k)+\omega_n^kfr(\omega_^k)}\\\large)=fl(\omega_^k)-\omega_n^kfr(\omega_^k)}\)

有了點值序列還不夠,我們還得根據點值求多項式。

令 \(g\) 為點值序列即 \(g_k=f(\omega_n^k)=\sum\limits_^f_i(\omega_n^k)^i\)

有 \(nf_k=\sum\limits_^(\omega_n^)^ig_i\)

也就是說,對 \(g\) 再做一遍 dft,不同的是初始單位根為 \(1\),每次乘上 \(\omega_n^\)

而 \(\omega_n^\) 是 \(\omega_n^\) 的共軛。

不會證根據上文可以寫出遞迴的版本,但常數較大。現在嘗試寫出非遞迴版。

考慮 \(0\dots n-1\) 次項係數遞迴到每一層時的位置。

以 \(n=8\) 為例

0 1 2 3 4 5 6 7

---------------

0 1 2 3 4 5 6 7

0 2 4 6|1 3 5 7

0 4|2 6|1 5|3 7

0|4|2|6|1|5|3|7

寫出第一行和最後一行的二進位制

|   | 原  | 現  |

| 0 | 000 | 000 |

| 1 | 001 | 100 |

| 2 | 010 | 010 |

| 3 | 011 | 110 |

| 4 | 100 | 001 |

| 5 | 101 | 101 |

| 6 | 110 | 011 |

| 7 | 111 | 111 |

我們發現,最後一行 \(i\) 位置上的數其實是位數為 \(\log n\) 時 \(i\) 在二進位制下反轉得到的數。 於是可以預處理出 \(i\) 在二進位制下反轉得到的數,也就能得到最後一行。此時他們都是 \(0\) 次,可以直接當做單位根代入得到的值。

然後列舉現在要處理 \(m\) 次多項式(\(m=2,4,8,.\dots,n\))。把序列分成 \(\dfrac\) 段,列舉段的起始點 \(l\),在這一段內列舉 \(k~(0\le k<\dfrac)\) 計算 \(f(l+k)\) 和 \(f(l+\dfrac+k)\).

**(多項式乘法):

const double pi = acos(-1);

int tr[n], n, m;

struct cp

inline cp operator - (const cp &c) const

inline cp operator * (const cp &c) const

cp() {}

cp(const double &_x, const double &_y) : x(_x), y(_y) {}

} f[n], g[n];

inline void swap(cp &x, cp &y)

void fft(cp *f, int fl)

} }}signed main()

FFT學習筆記

fft可用於解決一些卷積問題。一般問題形式如下 c a b c i ij 0a i b i j 若把a,b看成兩個次數為n多項式 a x ni 0 a i xi,b x ni 0b i x i 原問題等於兩個多項式相乘,c的次數等於2n 1 乙個次數界為n的多項式a的點值表達為n個點值對所組成的集合...

FFT學習筆記

今天doggu講了,開始覺得這玩意好強啊 後來自己看的時候發現蠻zz wys表示 贊同 所以很多自己覺得遙不可及,一輩子都不可能學會的東西只要慢慢理解,理解好了再把他化為自己的語言,歸到自己的世界裡 就覺得不是很難了,甚至很簡單.當然開始並不是,從 好難啊 到 這麼簡單困大爺我這麼久,之前腦子抽了z...

FFT 學習筆記

f x sum limits a i x i x 0,f x 0 x 1,f x 1 x f x 首先我們要了解複數 即 i sqrt 乙個數有實部和虛部 即 a x y i x,y 原來的實數運算相當於在乙個一維數軸上進行移動,複數則是在二維平面上運動 一句話來說就是摸長相乘,幅角相加 c 中提供...