快速数论变换NTT学习笔记

2024-01-26 13:04

本文主要是介绍快速数论变换NTT学习笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

什么是NTT?

数论变换(number-theoretic transform, NTT)是离散傅里叶变换(DFT)在数论基础上的实现。
NTT是一种计算卷积的快速算法,FFT也是其中一种。

但是FFT具有一些实现上的缺点,举例来说,向量必须乘上复数系数的矩阵进行处理,而且每个复数系数的实部和虚部是一个正弦及余弦函数,因此大部分的系数都是浮点数,也就是说,必须做浮点复数运算,计算量会比较大,并且浮点数运算产生的误差会比较大。

NTT解决的是多项式乘法带模数的情况,受到模数的限制,数也比较大。
在数学中,NTT 是关于任意环上的DFT。在有限域的情况下,通常称为数论变换,即NTT。

原根

FFT的实现是找单位圆上的 n n n个点 ω n 0 , ω n 1 , … , ω n n \omega_n^0, \omega_n^1, \dots, \omega_n^n ωn0,ωn1,,ωnn(称为单位根) ,然后对这些点进行FFT。因此,对于NTT,我们需要在取模域上找到和这个点等价的数。为了找到这 n n n个等价的数,我们要使用原根。

n n n为大于1的2的幂, p p p为质数且 n ∣ ( p − 1 ) n|(p-1) n(p1),即 n n n整除 p − 1 p-1 p1 ,则存在本原 n n n次方根。对于质数 p = q n + 1 p=qn+1 p=qn+1,(模 p p p意义下的)原根 g g g满足: g q n = 1 ( m o d p ) g^{qn}=1 (\mod p) gqn=1(modp),将 g n = g q ( m o d p ) = g p − 1 n ( m o d p ) g_n=g^q (\mod p)=g^{{p-1}\over n} (\mod p) gn=gq(modp)=gnp1(modp)看作 ω n \omega_n ωn的等价。

于是原根 g n g_n gn和单位根 ω n \omega_n ωn满足相似的性质!

原根和单位根的等价性

g n = g p − 1 n g_n=g^{{p-1}\over n} gn=gnp1

于是,
g n n = g n ⋅ p − 1 n = g p − 1 g_n^n=g^{n \cdot {p-1\over n}}=g^{p-1} gnn=gnnp1=gp1

g n n 2 = g p − 1 2 g_n^{n\over 2}=g^{p-1\over 2} gn2n=g2p1

g a n a k = g a k ( p − 1 ) a n = g k ( p − 1 ) n = g n k 【对应单位根消去引理】 g_{an}^{ak}=g^{\frac{ak(p-1)}{an}}=g^{\frac{k(p-1)}{n}}=g_n^k【对应单位根消去引理】 ganak=ganak(p1)=gnk(p1)=gnk【对应单位根消去引理】

可以得到:
g n n ≡ 1 ( m o d p ) 【对应单位根 ω n n ≡ 1 】 g_n^n \equiv 1 (\mod p) 【对应单位根\omega_n^n\equiv 1】 gnn1(modp)【对应单位根ωnn1

g n n 2 ≡ − 1 ( m o d p ) 【对应单位根 ω n n 2 ≡ − 1 】 g_n^{n\over 2} \equiv -1 (\mod p)【对应单位根\omega_n^{n\over 2}\equiv -1】 gn2n1(modp)【对应单位根ωn2n1

g n k + n 2 = g n k ⋅ g n n 2 = − g n k ( m o d p ) 【对应单位根折半引理】 g_n^{k+{n\over 2}}=g_n^{k}\cdot g_n^{n\over 2}=-g_n^{k} (\mod p)【对应单位根折半引理】 gnk+2n=gnkgn2n=gnk(modp)【对应单位根折半引理】

( g n k + n 2 ) 2 = g n 2 k + n = g n 2 k ⋅ g n n = g n 2 k ( m o d p ) (g_n^{k+{n\over 2}})^2=g_n^{2k+n}=g_n^{2k}\cdot g_n^n=g_n^{2k} (\mod p) (gnk+2n)2=gn2k+n=gn2kgnn=gn2k(modp)

我们发现单位根具有的性质原根都有,所以我们将 g n k g_n^k gnk g n k + n 2 g_n^{k+{n\over 2}} gnk+2n代入,本质上和将 ω n k \omega_n^k ωnk ω n k + n 2 \omega_n^{k+{n\over 2}} ωnk+2n代入并无二异!

在INTT中,乘单位根的共轭复数的操作也就会相应地变为乘原根在模意义下的逆元。

常见的模数和原根如下:
p = 1004535809 = 479 × 2 21 + 1 , g = 3 p = 998244353 = 7 × 17 × 2 23 + 1 , g = 3 p=1004535809=479\times 2^{21}+1, g=3 \\ p = 998244353=7\times 17\times2^{23}+1, g=3 p=1004535809=479×221+1,g=3p=998244353=7×17×223+1,g=3

快速数论变换(FNTT)

简而言之,FNTT是NTT增加分治操作之后的快速算法,也是FFT在数论基础上的实现。FNTT使用的分治办法,与FFT使用的分治办法完全一致。

DFT、FFT、NTT、FNTT的关系

  • 在 DFT与NTT的基础上,增加分治操作,得到FFT与FNTT。分治操作同FFT一致。
  • 在DFT与FFT的基础上,将复数加法与复数乘法替换为模 p p p意义下的加法和乘法,一般大小限制在0到 p − 1 p-1 p1之间;将本原单位根改为模 p p p意义下的相同阶数的本原单位根,阶数为2的幂,即可得到NTT与FNTT。

一大堆参考资料

  • 快速数论变换(NTT)超详解
  • OI Wiki 快速数论变换
  • 快速数论变换NTT
  • 快速傅立叶变换FFT学习笔记

这篇关于快速数论变换NTT学习笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/646885

相关文章

Python多线程实现大文件快速下载的代码实现

《Python多线程实现大文件快速下载的代码实现》在互联网时代,文件下载是日常操作之一,尤其是大文件,然而,网络条件不稳定或带宽有限时,下载速度会变得很慢,本文将介绍如何使用Python实现多线程下载... 目录引言一、多线程下载原理二、python实现多线程下载代码说明:三、实战案例四、注意事项五、总结引

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

C#使用Spire.XLS快速生成多表格Excel文件

《C#使用Spire.XLS快速生成多表格Excel文件》在日常开发中,我们经常需要将业务数据导出为结构清晰的Excel文件,本文将手把手教你使用Spire.XLS这个强大的.NET组件,只需几行C#... 目录一、Spire.XLS核心优势清单1.1 性能碾压:从3秒到0.5秒的质变1.2 批量操作的优雅

Python学习笔记之getattr和hasattr用法示例详解

《Python学习笔记之getattr和hasattr用法示例详解》在Python中,hasattr()、getattr()和setattr()是一组内置函数,用于对对象的属性进行操作和查询,这篇文章... 目录1.getattr用法详解1.1 基本作用1.2 示例1.3 原理2.hasattr用法详解2.

Mybatis-Plus 3.5.12 分页拦截器消失的问题及快速解决方法

《Mybatis-Plus3.5.12分页拦截器消失的问题及快速解决方法》作为Java开发者,我们都爱用Mybatis-Plus简化CRUD操作,尤其是它的分页功能,几行代码就能搞定复杂的分页查询... 目录一、问题场景:分页拦截器突然 “失踪”二、问题根源:依赖拆分惹的祸三、解决办法:添加扩展依赖四、分页

c++日志库log4cplus快速入门小结

《c++日志库log4cplus快速入门小结》文章浏览阅读1.1w次,点赞9次,收藏44次。本文介绍Log4cplus,一种适用于C++的线程安全日志记录API,提供灵活的日志管理和配置控制。文章涵盖... 目录简介日志等级配置文件使用关于初始化使用示例总结参考资料简介log4j 用于Java,log4c

使用Redis快速实现共享Session登录的详细步骤

《使用Redis快速实现共享Session登录的详细步骤》在Web开发中,Session通常用于存储用户的会话信息,允许用户在多个页面之间保持登录状态,Redis是一个开源的高性能键值数据库,广泛用于... 目录前言实现原理:步骤:使用Redis实现共享Session登录1. 引入Redis依赖2. 配置R

Linux如何快速检查服务器的硬件配置和性能指标

《Linux如何快速检查服务器的硬件配置和性能指标》在运维和开发工作中,我们经常需要快速检查Linux服务器的硬件配置和性能指标,本文将以CentOS为例,介绍如何通过命令行快速获取这些关键信息,... 目录引言一、查询CPU核心数编程(几C?)1. 使用 nproc(最简单)2. 使用 lscpu(详细信

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和