From b2f0a89921d53b5cdf016ecfba8d875183a5b511 Mon Sep 17 00:00:00 2001 From: Sunlight Zero <77185599+Sunlight-zero@users.noreply.github.com> Date: Fri, 3 May 2024 14:08:06 +0800 Subject: [PATCH] =?UTF-8?q?fix(math/poly/fft):=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E9=80=92=E5=BD=92=E7=89=88=20FFT=20=E4=BB=A3=E7=A0=81=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原来的 FFT 中,定义了旋转角度 step,并通过 cur *= step 不断计算下一个单位根。这种做法会随着循环逐渐累积浮点数的精度误差,最终误差太大,在洛谷模板题 P3803 会 WA。因此修改为直接调用 sin,cos 计算每一次的单位根。 --- docs/math/poly/fft.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/math/poly/fft.md b/docs/math/poly/fft.md index 349fc5ebdef2..9b1db63a9198 100644 --- a/docs/math/poly/fft.md +++ b/docs/math/poly/fft.md @@ -247,16 +247,13 @@ $$ Comp *g = f, *h = f + n / 2; // 递归 DFT DFT(g, n / 2, rev), DFT(h, n / 2, rev); - // cur 是当前单位复根,对于 k = 0 而言,它对应的单位复根 omega^0_n = 1。 - // step 是两个单位复根的差,即满足 omega^k_n = step*omega^{k-1}*n, - // 定义等价于 exp(I*(2*M_PI/n*rev)) - Comp cur(1, 0), step(cos(2 * M_PI / n), sin(2 * M_PI * rev / n)); for (int k = 0; k < n / 2; ++k) { // F(omega^k_n) = G(omega^k*{n/2}) + omega^k*n\*H(omega^k*{n/2}) + // cur 是当前单位复根,定义等价于 exp(I*(2*M_PI/n*rev)) + Comp cur(cos(2 * k * M_PI / n), sin(2 * k * M_PI * rev / n)); tmp[k] = g[k] + cur * h[k]; // F(omega^{k+n/2}*n) = G(omega^k*{n/2}) - omega^k_n*H(omega^k\_{n/2}) tmp[k + n / 2] = g[k] - cur * h[k]; - cur *= step; } for (int i = 0; i < n; ++i) f[i] = tmp[i]; }