单位根定义
方程 xn=1 在 C 上根据代数基本定理恰好有 n 个根,记作 ωn,ω2n…ωnn。
由于复数相乘的规则是模长相乘,幅角相加,可以看到,这 n 个根所对应的向量都是单位向量,在复平面上对应着单位圆上的 n 个等分点。
另一种理解是根据欧拉公式 eix=cos(x)+isin(x)。这个公式将 exp 函数解析延拓到了复数域上。我们一旦注意到 e2πn=1,就可以推出 ωn=e2πin=cos(2πn)+isin(2πn)。这带给了我们在 R 上计算单位根的可能性。
根据这个几何意义,我们发现 ωi+nn=ωin 是很自然成立的。这意味着单位根和在模 n 意义下的运算具有很相似的性质。
用上指标来表示单位根的编号也是一个及其明智的选择,我们有 ωin=(ωn)i,这也就意味着实际运用时我们往往只需要先求一个单位根再依此推出所有的根。
先求一个根再依此推出所有的根,这令我们回想起数论中我们求最小正原根然后求所有原根的过程。原根也是跟模 φ(m) 意义下的运算有着千丝万缕的联系。
把这两个东西联系起来,单位根有欧拉公式 e2πn=1,原根有欧拉定理 gφ(m)≡1(modm)。
相似地,我们可以定义模意义下的单位根 ωn=gφ(m)n。模意义下的 n 次剩余经常不存在,所以一般只在模数比较特殊(如 998244353)时使用模意义下的单位根。
DFT 与循环卷积
学习 OI,我们见识了定义在各种各样运算上的“卷积”,以及为了计算这种卷积定义的各种各样的“变换”。
形式化的说对于某种运算 ⊕,两个序列 f,g 的 ⊕ 运算卷积得到的结果 f∗g 满足:
(f∗g)k=∑i⊕j=kfigj
为了快速计算这种卷积,我们定义线性变换 A 满足 A(f)⋅A(g)=A(f∗g)(⋅ 表示点乘),A 存在逆 A−1,且 A(f),A−1(f) 均可快速计算。
拆开分析 A 矩阵应该满足性质 Ai,jAi,k=Ai,j⊕k。
当我们将 ⊕ 定义为模 n 意义下的加法时,ωn 构成的范德蒙德矩阵 Ai,j=ωijn 完美满足了上述条件。此时这个线性变换过程计算的就是 f,g 的循环卷积。
也就是说,当我们要计算循环卷积的若干次幂时可以先得到多项式的 n 个点值 F(ω0n),F(ω1n)…F(ωn−1n),快速幂之后插值回去。
这 n 个点值正好是等比数列的形式,我们可以用 Chirp-Z 变换计算。Chirp-Z 变换实际上就是一个 trick。注意到 ij=(ij2)−(i2)−(j2),那么 F(ci)=∑n−1j=0cijfj=c−(i2)∑n−1j=0c(ij2)c−(j2)fj。减法卷积计算即可。
单位根反演
单位根具有类似“循环”的性质,我们可以利用这种性质处理整除与模相关的问题。
考虑下述式子:
n−1∑i=0ωikn
大多数情况下这是一个等比数列,所以结果是 ωnkn−1ωkn−1=0。
但对于 ωkn=1,也就是 n|k 的情况,退化成等差数列,式子的值是 n。
即:
[n|k]=1nn−1∑i=0ωikn
常见手段是用它来处理式子中的 mod。比如说可以用它来推导循环卷积:
Ck=n−1∑i=0n−1∑j=0[(i+j)≡k(modn)]AiBj=n−1∑i=0n−1∑j=0[n|(i+j−k)]AiBj=1nn−1∑i=0n−1∑j=0AiBjn−1∑t=0ω(i+j−k)tn=1nn−1∑t=0−ωktn(n−1∑i=0Aiωitn)(n−1∑j=0Bjωjtn)
注意到两个括号中就是两个多项式 DFT 的结果,而括号外面就是 IDFT 的结果。
单位根反演一个比较常见的用法就是用来提取多项式的系数。
众所周知,F(1) 代表的就是多项式的系数之和 ∑n−1i=0fi。当我们想提取多项式的等差数列下标所对应的系数之和时,可以考虑单位根反演。
1kk−1∑i=0F(ωik)=1kk−1∑i=0n−1∑j=0fjωijk=n−1∑j=0[k|j]fj
比如复读机这道题,对于指数生成函数 F(x)=ex,可以用上述式子提取对应项系数后暴力二/三项式展开计算。
为了这叠醋包的饺子。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~