网上很少有人提到,写的也很简单,事实上就是很简单...
(Bluestein's Algorithm),用以解决任意长度(DFT)。
考虑(DFT)的形式:$$egin{aligned}y_k&=sum_{i=0}^{n-1}a_iomega_n^{ki}&=sum_{i=0}^{n-1}a_iomega_{2n}^{k^2+i^2-(k-i)^2}&=omega_{2n}^{k^2}sum_{i=0}^{n-1}a_iomega_{2n}^{i^2}omega_{2n}^{-(k-i)^2}end{aligned}$$
注意到(sum)是个卷积,可以用(FFT/NTT)计算。所以(Bluestein)的复杂度是(O(nlog n))的。
具体:(k-i)可能是负的,所以对后一项右移(n)位,令(f_i=a_iomega_{2n}^{i^2}, g_i=omega_{2n}^{-(i-n)^2}),那么(y_k=omega_{2n}^{k^2}sum_{i}f_ig_{n+k-i}=omega_{2n}^{k^2}(f imes g)_{n+k})。
(IDFT)同理,可以直接令(omega_{2n}=omega_{2n}^{-1}),代到(DFT)的式子里,也可以一样的推一下:$$egin{aligned}c_k&=frac{1}{n}sum_{i=0}^{n-1}a_iomega_n^{-ki}&=frac{1}{n}sum_{i=0}^{n-1}a_iomega_{2n}^{k^2+i^2-(k+i)^2}&=frac{1}{n}omega_{2n}^{k^2}sum_{i=0}^{n-1}a_iomega_{2n}^{i^2}omega_{2n}^{-(k+i)^2}end{aligned}$$
令(f_i=a_iomega_{2n}^{i^2}, g_i=omega_{2n}^{-(2n-1-i)^2}),那么(c_k=frac{1}{n}omega_{2n}^{k^2}sum_if_ig_{2n-1-k-i}=omega_{2n}^{k^2}(f imes g)_{2n-1-k})。
上面是一般的做法(其实就是个(trick)),但是(dls)指出有更好一些的做法:
像这样写成平方需要(omega_{2n})(有些题可能不存在(2n)次单位根),就可以用:(ij=inom{i+j}{2}-inom i2-inom j2)来替换:(y_k=omega_n^{-inom k2}sum_{i=0}^{n-1}a_iomega_n^{-inom i2}omega_n^{inom{i+j}{2}})。
例题
事实上我觉得除了循环卷积需要任意长度(DFT)外,其它地方就用不到了...(应该是我做题少)
1. 正睿 青岛集训 Day4 A.智慧树
见这里。
2. BZOJ.1919.[CTSC2010]性能优化
也是循环卷积裸题...(做不出来不负责请找dls
3. HDU.4656.Evaluation
类似(Bluestein)的(trick)应用。题解见这里(我就咕咕咕了)。