快速数论变换
本文不会从头开始介绍NTT算法,所以需要先了解FFT:
永远在你身后:快速傅里叶变换(FFT)求解多项式乘法zhuanlan.zhihu.com
除此之外,先简单的铺垫一些数论的概念
设
![]()
是正整数,
![]()
是整数,若
![]()
模
![]()
与
![]()
模
![]()
的余数相同,则称
![]()
和
![]()
模
![]()
同余,记作:
![]()
。随便举几个例子:
设
![]()
是互素的整数,
![]()
,
![]()
,使得
![]()
成立的
最小正整数
![]()
称为
![]()
模
![]()
的
阶,记为
![]()
(这个记号是照搬教材的,有的资料会记作
![]()
,不过这个不重要)
例如,为了计算 2 模 7 的阶,依次计算 2 的各个幂模 7 的余数:
因此有
在介绍原根之前,先说一下欧拉函数:设有一个正整数
![]()
,则欧拉函数返回小于
![]()
并且与
![]()
互素的正整数的
个数,记作
如果
![]()
是互素的正整数,当
![]()
时,称
![]()
是
模
的原根
,或者
的
原根
例如,现在求 3 模 7 的阶:
因为 7 是素数,所以
![]()
,因此
![]()
,所以 3 是 7 的一个原根
好了,铺垫完毕,下面进入正题,之前介绍的FFT算法之所以有用,是因为单位根(
![]()
)的特殊性质:对于
![]()
两个正整数,
![]()
,则
![]()
成立当且仅当
![]()
。简单的说就是
![]()
两两之间互不相等
明白这个关键之后,再来看看原根的性质。给定一个奇素数
![]()
,其原根为
![]()
,对于
![]()
两个正整数,
![]()
,同样有
![]()
成立当且仅当
![]()
。可以看出原根和单位根的性质非常相似,不过还不能直接使用原根来替代单位根,下面进行进一步的构造。
设有一个形如
![]()
素数
![]()
(例如
![]()
)及其原根
![]()
,以及正整数
![]()
(