myy txdy!
三模 NTT
这还讲啥呢……
都 0202 年了还有人写三模 NTT 吗……
拆系数 FFT
整一个阈值 W,把系数拆成 aW+c (c<W) 的形式。
一般设 W=215=32768。
那么需要 7 次 DFT,起码比隔壁 9 次的三模好(虽然人家是 NTT)
三次变两次
若我们有俩整系数多项式 A,B 要求它们的卷积,我们可以设 F(x)=A(x)+iB(x),G(x)=A(x)−iB(x)
如果我们能求出 F,G 的点值表达,也就能当成二元方程来解出 A,B 的点值表达。
然而,实际上,只需要求 F 的点值表达,就能推出 G 的点值表达。
设 FDFT(k)=F(ωkn),GDFT(k)=G(ωkn)。
再令 conj(a+bi)=a−bi 即共轭负数。
再用小写字母表示多项式的系数序列。
则 FDFT(k)=A(ωkn)+iB(ωkn)=n−1∑j=0(aj+ibj)ωjknGDFT(k)=n−1∑j=0(aj−ibj)ωjkn=n−1∑j=0(aj−ibj)(cos2πjkn+isin2πjkn)=n−1∑j=0((ajcos2πjkn+bjsin2πjkn)+i(ajsin2πjkn−bjcossin2πjkn))=conj(n−1∑j=0((ajcos2πjkn+bjsin2πjkn)−i(ajsin2πjkn−bjcos2πjkn)))=conj(n−1∑j=0((ajcos−2πjkn−bjsin−2πjkn)+i(ajsin−2πjkn+bjcos−2πjkn)))=conj(n−1∑j=0(aj+ibj)(cos−2πjkn+isin−2πjkn))=conj(n−1∑j=0(aj+ibj)ω−jkn)=conj(n−1∑j=0(aj+ibj)ω(n−k)jn)=conj(FDFT(n−k))
注意当 k=0 时 n−k≡0(modn)。
将该优化应用于拆系数 FFT
若有两个数 aW+b 和 cW+d 相乘,则结果应为 acW2+(ad+bc)W+bd。
于是 7 次 DFT 做完(就是上面那个朴素的拆系数 FFT)
但是,注意到 (a+bi)(c+di)=(ac−bd)+(bc+ad)i(a−bi)(c+di)=(ac+bd)+(ad−bc)i
于是我们把 a+bi,a−bi,c+di 分别 DFT 然后这样卷起来再 IDFT 回来,求出 ac,ad+bc,bd 就行了。
这样要 5 次。
然而 conj(a+bi)=a−bi,于是运用上面那个就可以少一次。
然后就变成 4 次了。
(听说还有 3.5 次然而我不会)
代码:
1 |
|