快速数论变换(fast number-theoretic transform,FNTT)
2024年1月15日 12:55:59 记
大数乘法与多项式乘法(Polynomial Multiplication)
两个大数如$12345$和$67890$,用多项式表达:
在进行多项式乘法的时候,得到$h(x)$的系数便可以变相表示为两个大整数之积
转为列表
逆序一下,符合高位在左的书写习惯
进位
快速傅里叶变换(Fast Fourier Transform,FFT)
回到开始的多项式,估算原积不超过$10$位,不足$2^k$位数则用$0$补齐(方便后续递归分治)
正常的乘法,需要对$f(x)$和$g(x)$的每一项都两两相乘,复杂度$O(n^2)$很高
为了描述这些多项式方程,除了采用系数表示法($n$个系数),还可以使用描点表示法($n$个点),例如方程$y=1x+0$可以用点$(0,0),(1,1)$唯一确定,方程$y=1x^2+2x+3$可以用点$(0,3),(1,6),(2,11)$唯一确定,即具有$n$个系数的$(n-1)$次多项式方程可以由$n$个不同的点唯一确定
那么对于$7$次多项式方程
任取$7$个
得到$7$个函数值
为了求这$7$个函数值,可以用矩阵方法表示(用列向量主要是因为横向量太长了Typora写不下)
如若使用编程实现该功能,复杂度$O(n^2)$依然没有优势
重新回到$f(x)$,wiki上对奇偶函数的代数结构有这样的描述:
偶函数的任何线性组合皆为偶函数,且偶函数会形成一个实数上的向量空间。相似地,奇函数的任何线性组合皆为奇函数,且奇函数亦会形成一个实数上的向量空间,实际上,”所有“实值函数之向量空间为偶函数和奇函数之子空间的直和。换句话说,每个定义域关于原点对称的函数都可以被唯一地写成一个偶函数和一个奇函数的相加:
类似地,将原式$f(x)$奇偶性分解
记
则有
如此一来计算$f(x_i)$的值只需计算$q_e(x_i),q_o(x_i)$的值即可,观察到$q(x)$与$f(x)$形似,也可以使用同样的逻辑进一步拆分分治,使用递归的逻辑连接起来。
为了更好的利用奇偶性质,$x_i$的值不任取,如在本例$n=8$中选取
这样一来
综上写出伪代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13def fft(a):
#a = [a_0,a_1,a_2,...,a_{n-1}]
#return [f(w^0),f(w^1),f(w^2),...,f(w^{n-1})]
if (n==1) return [a_0]
pe = [a_0,a_2,...,a_{n-2}]
po = [a_1,a_3,...,a_{n-1}]
q_o = fft(p_e)
q_e = fft(p_e)
w = cos(2pi/n) + i sin(2pi/n)
for j in [0,1,2,...,n/2-1]:
f(w^j) = q_e[j] + w^j q_o[j]
f(w^{j+n/2}) = q_e[j] - w^j q_o[j]
return [f(w^0),f(w^1),f(w^2),...,f(w^{n-1})]
以上,实现了从系数表示到点列表示的过程,即主要是为了实现这个计算
p.s:突然发现这好像就是我当时参加的TACA的原题啊喂
不妨把这个大矩阵记作$W$
想要实现从点列表示转成系数表示,就需要求得这个$W$矩阵的逆矩阵$W^{-1}$
离散傅里叶变换矩阵(Discrete Fourier Transform matrix,DFTmtx)
离散傅立叶变换矩阵是将离散傅立叶变换以矩阵乘法来表达的一种表示式
DFT矩阵定义
或
注意:此处$\omega$在指数上是否存在负号区别于之前的$\omega$,同时此处矩阵$W$有正规化因数$\frac{1}{\sqrt{N}}$
其逆矩阵是
下验证$WT=I$
当且仅当$i=j$时有
当$i \ne j$时有
至此$WT=I$验证完毕
快速傅里叶逆变换(Inverse Fast Fourier Transform,IFFT)
根据上面的式子,我们得到了
那么回到最先的式子
可以有
即
由于
这意味着先前得出的FFT逻辑完全可以把所有的$\omega$换成$\tau$便可完成IFFT的过程,再一次实现函数复用
现在剩余一个问题,$\omega$是一个复数,在$n$不大的情况下计算误差不大,但是当$n$很大,计算误差和三角函数计算时间都是问题,于是要引入有限域
有限域(finite field)
一点儿没学明白,查资料也写不出来多少$QAQ$
大致运算:
如在$\mathrm{mod} \space 5 $下,
根据此类性质,可以写出C函数如下
1 | typedef long long int lli; |
快速数论变换(fast number-theoretic transform,FNTT)
先前FFT中选取$\omega = e^{\frac{2i\pi}{n}}$的性质主要有三:
- 所有计算除了系数$a_i$只需要计算$\omega ^{k}$即可,便于计算
- $\omega ^{k+\frac{n}{2}}=-\omega ^{k},\omega^{n}=1$
- $\omega ^{k},k\in Z_{n}$各不相同
而在一个有限域内,也同样有数可以满足这两条特性,如$p=84906529,\omega =213016,n=16$,$\omega^k \pmod{p} $的各值如下
这样的$\omega$也同样符合先前的性质,因此不妨把FFT中的所有运算都转为模$p$数域下的运算,$\omega$换成整数的$\omega$
1 | int FNTT(int *pa,int w,List a,int *f){ //FNTT快速数论变换(基于FFT快速傅里叶变换) |
那么如何选择$p,\omega$?
对于质数$p = q2^m+1$,原根$g$满足$g^{q2^k} \equiv 1\pmod{p}$,将$g_n \equiv g^q \pmod{p}$看作$\omega$的等价,则其满足相似的性质
p.s:数论知识好多,不会证明;w;
综上,写成完整C语言代码如下
1 |
|
参考学习
超硬核FFT快速傅里叶变换讲解,高效进行高精度乘法运算! - Bilibili
最讨厌做算法题的时候出现浮点数了,有什么方法可以避免?斐波那契数列和FFT均可适用! - Bilibili
__END__