今天学什么之NTT

NTT(数论变换,Number Theoretic Transform)

一、NTT的数学原理

NTT是快速傅里叶变换(FFT)在模数域下的等价形式。它主要用于大整数乘法等问题中,尤其是在模数运算环境下。NTT的优点在于它避免了浮点数运算,减少了误差的积累,特别适用于加密和编码领域。

1.1 知识点补充

1.1.1模数运算环境
模数运算是指在取余运算的过程中,只考虑余数而忽略商的计算。在模数运算中,我们通常使用一个模数(模)来对一个数进行取余运算。

举个简单的例子,具体的计算步骤如下:

假设我们要计算13对5取模的结果,我们要计算 13 mod 5
首先,我们将13除以5,得到商2和余数3。
在模数运算中,我们只关心余数,因此13 mod 5 的结果为3。

因此,13 mod 5 的结果是3。在计算机科学和密码学领域,模数运算经常被使用,特别是在加密算法和校验方法中。

1.1.2 符号
  • 在数学中,符号 “|” 通常表示“整除”。所以当我说到 “n | (p-1)” 时,意思是 n 能够整除 (p-1),也就是说,(p-1) 是 n 的倍数。
  • List item
1.1.3 原根和
  • 原根(Primitive Root):在数论中,给定一个正整数n,如果存在一个整数a,使得对于任意与n互质的正整数k,都存在一个正整数m,使得a^m≡k ( mod n) ,那么a就被称为模n的原根。换句话说,原根是一个可以生成模n剩余类的整数。

举个例子,考虑模12的情况,我们可以计算出2、5和11都是模12的原根。例如,以2为底的幂次运算:

2^1≡2 ( mod 12)
2^2≡4 ( mod 12)
2^3≡8 ( mod 12)
2^4≡4 ( mod 12)
2^5≡10 ( mod 12)
2^6≡2 ( mod 12)...

我们可以看到,对于与12互质的任何数k,总能找到一个m,使得2m≡k(mod12)2m≡k(mod12)。因此,2是模12的原根。

  • 单位根(Unit Root):在复数域中,给定一个正整数n,单位根是指满足方程xn=1xn=1的复数解。单位根的个数为n,可以用复数平面的单位圆上的点来表示。

    举个例子,考虑单位根的情况,我们来看看模5的单位根。方程x5=1x5=1有五个根,分别是1、e2πi/5e2πi/5、e4πi/5e4πi/5、e6πi/5e6πi/5和e8πi/5e8πi/5,其中ee是自然对数的底,i是虚数单位。这五个复数都满足x5=1x5=1的条件,因此它们都是模5的单位根。

总结:原根是数论中与模n的剩余类相关的概念,单位根是复数域中与方程xn=1xn=1相关的概念。两者在不同领域的数学中有不同的含义和应用。

1.2 原理概述

1.2.1 单位根

在NTT中,我们使用的是n阶原根的幂作为单位根,而不是FFT中的复数单位根。如果有一个数ω满足ω^n ≡ 1 (mod p),其中p是质数,且n | (p-1),那么称ω是模p的n次本原单位根。

1.2.2 DFT和IDFT

NTT基于离散傅里叶变换(DFT)和其逆变换(IDFT)的概念,但是在有限域(模p)中进行计算。对于一个长度为n的序列a,其NTT变换定义为另一个序列A,其中A[k] = Σ(a[j] * ω^(jk)) mod p,j从0到n-1。逆变换则用ω的逆元进行计算。

1.2.3 蝴蝶操作

NTT和FFT一样,通过分治策略实现快速计算。这个过程中的基本操作被称为“蝴蝶操作”,它将序列分为“偶数部分”和“奇数部分”,然后递归地应用变换,最后合并结果。

1.2.4 模数选择

为了使NTT正确运行,模数p需要满足特定条件:p = kn + 1,其中k是正整数,这保证了n阶原根的存在。此外,为了简化逆元和模逆的计算,通常选择p使得它是一个质数。

1.3 示例

假设我们要对序列a = [1, 2, 3, 4]进行NTT变换,选择n=4,p=17(一个满足条件的模数,因为17-1可以被4整除),并找到一个4次本原单位根ω=3(因为3^4 ≡ 1 (mod 17))。

计算A[0]:
    A[0] = 13^0 + 23^0 + 33^0 + 43^0 = 10 (mod 17)

计算A[1]:
    A[1] = 13^0 + 23^1 + 33^2 + 43^3 = 1 + 6 + 9 + 8 = 24 ≡ 7 (mod 17)

计算A[2]:
    A[2] = 13^0 + 23^2 + 33^4 + 43^6 = 1 + 9 + 3 + 4 = 17 ≡ 0 (mod 17)

计算A[3]:
    A[3] = 13^0 + 23^3 + 33^6 + 43^9 = 1 + 8 + 4 + 1 = 14 (mod 17)

所以,NTT变换的结果是A = [10, 7, 0, 14]。

1.4 简单算法

用Python编写的NTT算法示例:

python

def ntt(a, p, omega):
“”"
NTT算法实现

参数:
a -- 输入的序列
p -- 模数
omega -- 本原单位根

返回值:
A -- NTT变换后的结果序列
"""
n = len(a)

if n == 1:
    return a

# 分治:将输入序列分为偶数部分和奇数部分
even = ntt(a[0::2], p, omega)  # 偶数部分
odd = ntt(a[1::2], p, omega)   # 奇数部分

# 合并结果
A = [0] * n
factor = 1
for k in range(n//2):
    t = (odd[k] * factor) % p
    A[k] = (even[k] + t) % p
    A[k + n//2] = (even[k] - t) % p
    factor = (factor * omega) % p

return A
示例用法
a = [1, 2, 3, 4]
p = 17
omega = 3
A = ntt(a, p, omega)
print(A)

这段代码中,ntt 函数使用递归方式实现了NTT算法。它首先检查输入序列的长度,如果长度为1,则直接返回该序列。否则,它将输入序列分为偶数部分和奇数部分,然后递归地对它们进行NTT变换。最后,通过合并结果得到最终的NTT变换序列。

在示例中,我们使用了输入序列 [1, 2, 3, 4],模数 p = 17,本原单位根 omega = 3。运行代码后,将会输出NTT变换后的结果序列。

至此,我还没完全学明白,我还要再摸索摸索

  • 25
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值