多项式:一个以为变量的多项式定义在一个代数域上,将多项式函数表示为
其中为多项式系数。如果一个多项式的最高次的非零系数是,则称的次数是k,。任何一个大于一个多项式次数的整数都是该多项式的次数界。
1) 对于多项式加法:如果和是次数界为的多项式,那么它们的和也是一个次数界为n的多项式。
Horner Rule:对于多项式在给定点的求值运算即计算。在时间复杂度内完成运算。
类似的,对于两个分别用系数向量和表示的多项式进行相加时,所需的时间为。
2) 对于多项式乘法:举个例子
。
注意观察,上式中的系数向量其实是输入向量和。
点值表达(Point Value):给定一组个不同点集,点值表达就是一个由n个点值对所组成的集合,。
所有不同,。
定理:(插值多项式的唯一性)对于任意n个点值对组成的集合,所有不同;那么存在唯一的次数界为的多项式,满足
其中范德蒙德矩阵表示为,该矩阵的行列式值为。如果所有不同,则该矩阵是可逆的(非奇异)。给定点值表达,可以唯一确定系数:
求解方法:
也就是说我们将原始的的矩阵划分成两个几乎相似的的矩阵。
显然这是一个分治的思想,
我们这里用的技巧就是用和来评估多项式A,但要注意,对于和的输入都是正数。
所以,可以针对上述做出规律总结:
单位复数根:次单位复数根式满足的复数。对于,这些根就是。值称为主n次单位根。
n个n次单位复数根在乘法意义下形成一个群。
,
用点值表达式求解多项式乘法。如果,则对于任意点。由于C的次数界为,要插值获得唯一的多项式C,需要2n个点值对。必须对A和B的点值表达进行扩展,使每个多项式都包含个点值对。给定A的扩展点值表达,B的对应扩展点值表达为。
则C的点值表达为。
应用:
1)数字乘法运算,和多项式乘法类似,A*B的操作就是用A每一位上的数字乘以B每一位上的数字。尤其是在大数乘法中,FFT可以大幅度加快运算。
2)给定A到B的不同长度路径详细数据,B到C的不同路径长度详细数据,求A到C不同长度路径的数量。可以把A到B和B到C不同长度的路径看成不同次数的项。例如:A到B有3条长度为4,2条长度为5的路径;B到C有1条长度为2,4条长度为3的路径。那么A到C不同长度路径的数量等于得到的各项的系数,转化成多项式相乘问题之后,就可以利用FFT来加快运算速度了。
异曲同工:(30.1-6) 考虑两个集合A和B,每个集合包含取值范围在0~10n之间的n个整数。我们希望计算出A与B的笛卡尔和,定义如下:C={x+y:x∈A,y∈B}注意到,C中整数值的范围在0~20n之间。我们希望找到C中的元素,并且求出C中的每个元素可表示为A中元素与B中元素和的次数。请在O(nlgn)时间内解决问题。(提示:请用次数至多是的多项式来表示A和B)。
解法:多项式A与B是系数均为1的,指数为范围在之间的n个整数。计算可以用DFT在时间内计算出。然后再遍历一下C,C的系数就是A与B的笛卡尔和项的出现次数。
3)在一个给定的数组中,判断是否有i,j,k满足a[i]+a[j]=a[k],有没有比较好的算法?
用fft可以做到nlogn求出所有可能的和,再用hashset存下来,然后遍历一遍看其中是否存在与原数组相同的数。但其实fft的复杂度和这些数的大小是相关的,这个nlogn就像01背包问题的dp解法一样,是个伪复杂度,并没有解决一般情况下的3sum问题。fft的复杂度严格来说是mlogm + n的,其中m是数组里每个数绝对值的最大值,n是数组大小。
实现:
对输入序列长度不是2的整数次幂,其实只要对长度取一下对数即可,例如:输入长度如果是37,首先把37*2,拓展成74(这个是FFT必须的),然后对74取log2上取整即可,得到27=128,因此在74后面再添加54个0。
参考资料:
1)CSE548-lecture-4.pdf
2)算法导论第30章
3)http://blog.csdn.net/z84616995z/article/details/24308087
4)https://en.wikipedia.org/wiki/3SUM#a.2Bb.3Dc
5)http://jeffe.cs.illinois.edu/teaching/algorithms/