引入

\(\tt NTT\) 和 \(\tt FFT\) 有什么不一样呢?

就是 \(\tt NTT\) 是可以用来取模的,而且没有复数带来的精度误差。

最最重要的是据说 \(\tt NTT\) 常数小的很,可以在这一方面吊打 \(\tt FFT\) 。

至于对于不用取模的多项式乘法怎么做,可以给他附一个非常大的模数。

但是如果遇到有非整数的系数的多项式还是只能看 \(\tt FFT\) 了。

正文

\(\tt NTT\) 的前置知识比 \(\tt FFT\) 的要简单的多。

原根

对于 \(p\) 和 \(g\) 两个整数,若

\[g^i\ \text{mod} \ g\ (1\leq i\leq p -1)
\]

这个式子的值都不相同,那么 \(g\) 是 \(p\) 的原根。

通常 \(\tt NTT\) 的题目会给 \(998244353\) , \(1004535809\) , \(469762049\) 这几个模数。

他们的原根都是 \(3\) 。

但是这个我嫌不够过瘾,所以就放一个在网上找到的牛逼原根表。

  1. //(g 是mod(r*2^k+1)的原根)
  2. 素数 r k g
  3. 3 1 1 2
  4. 5 1 2 2
  5. 17 1 4 3
  6. 97 3 5 5
  7. 193 3 6 5
  8. 257 1 8 3
  9. 7681 15 9 17
  10. 12289 3 12 11
  11. 40961 5 13 3
  12. 65537 1 16 3
  13. 786433 3 18 10
  14. 5767169 11 19 3
  15. 7340033 7 20 3
  16. 23068673 11 21 3
  17. 104857601 25 22 3
  18. 167772161 5 25 3
  19. 469762049 7 26 3
  20. 1004535809 479 21 3
  21. 2013265921 15 27 31
  22. 2281701377 17 27 3
  23. 3221225473 3 30 5
  24. 75161927681 35 31 3
  25. 77309411329 9 33 7
  26. 206158430209 3 36 22
  27. 2061584302081 15 37 7
  28. 2748779069441 5 39 3
  29. 6597069766657 3 41 5
  30. 39582418599937 9 42 5
  31. 79164837199873 9 43 5
  32. 263882790666241 15 44 7
  33. 1231453023109121 35 45 3
  34. 1337006139375617 19 46 3
  35. 3799912185593857 27 47 5
  36. 4222124650659841 15 48 19
  37. 7881299347898369 7 50 6
  38. 31525197391593473 7 52 3
  39. 180143985094819841 5 55 6
  40. 1945555039024054273 27 56 5
  41. 4179340454199820289 29 57 3

转载 这篇博客的

\(\tt NTT\)

其实 \(\tt NTT\) 就是把原根替换 \(\tt FFT\) 中的单位根。

\(\tt FTT\) 之所以牛逼,是因为 \(\omega\) 有一些非常奇妙的性质。

然后神仙们发现其实原根也有非常牛逼的性质。

当此时的合并区间的长度为 \(L=2\times l\) 时

单位根是

\[\cos\frac{2\pi}{L}+i\times\sin\frac{2\pi}{L}=\cos\frac{\pi}{l}+i\times\sin\frac{\pi}{l}
\]

而原根是:

\[g^{\frac{p-1}{L}}=g^{\frac{p-1}{2\times l}}
\]

其他和 \(\tt FFT\) 就基本没有什么区别了。

  1. inline void NTT(int a[], int len, int inv) {
  2. int bit = 0;
  3. while ((1 << bit) < len) ++bit;
  4. for (int i = 0; i <= len - 1; i++) {
  5. rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1));
  6. if (i < rev[i]) std::swap(a[i], a[rev[i]]);
  7. }
  8. for (int mid = 1; mid < len; mid *= 2) {
  9. int tmp = power(g, (mod - 1) / (mid * 2));
  10. if (inv == -1) tmp = power(tmp, mod - 2);
  11. for (int i = 0; i < len; i += mid * 2) {
  12. int omega = 1;
  13. for (ll j = 0; j < mid; ++j, omega = omega * tmp % mod) {
  14. int x = a[i + j];
  15. int y = omega * a[i + j + mid] % mod;
  16. a[i + j] = (x + y) % mod;
  17. a[i + j + mid] = (x - y + mod) % mod;
  18. }
  19. }
  20. }
  21. }

这个代码也不是我原创的,在网上随便贺了一篇代码。

调用的话就和 \(\tt FFT\) 基本上一模一样。

NTT 学习笔记的更多相关文章

  1. FFT和NTT学习笔记_基础

    FFT和NTT学习笔记 算法导论 参考(贺) http://picks.logdown.com/posts/177631-fast-fourier-transform https://blog.csd ...

  2. NTT学习笔记

    和\(FFT\)相对应的,把单位根换成了原根,把共轭复数换成了原根的逆元,最后输出的时候记得乘以原\(N\)的逆元即可. #include <bits/stdc++.h> using na ...

  3. FFT、NTT学习笔记

    参考资料 picks miskcoo menci 胡小兔 unname 自为风月马前卒 上面是FFT的,学完了就来看NTT吧 原根 例题:luogu3803 fft优化后模板 #include < ...

  4. FFT&NTT学习笔记

    具体原理就不讲了qwq,毕竟证明我也不太懂 FFT(快速傅立叶变换)&NTT(快速数论变换) FFT //求多项式乘积 //要求多项式A和多项式B的积多项式C //具体操作就是 //DFT(A ...

  5. FFT/NTT 学习笔记

    0. 前置芝士 基础群论 复数 \(\mathbb C = \mathbb R[x^2+1]\) 则有 \(i^2+1=(-i)^2+1=0\),\(i \in \mathbb C - \mathbb ...

  6. 任意模数NTT学习笔记

    这两天有点颓,所以东西学的也很慢...这个一眼就能推出来的活生生卡了我两天.. 说几个细节: 柿子: \[f*g = (\frac{f}{M} +f\%m)*(\frac{g}{M} +g\%m) \ ...

  7. [学习笔记]NTT——快速数论变换

    先要学会FFT[学习笔记]FFT——快速傅里叶变换 一.简介 FFT会爆精度.而且浮点数相乘常数比取模还大. 然后NTT横空出世了 虽然单位根是个好东西.但是,我们还有更好的东西 我们先选择一个模数, ...

  8. 「学习笔记」FFT 之优化——NTT

    目录 「学习笔记」FFT 之优化--NTT 前言 引入 快速数论变换--NTT 一些引申问题及解决方法 三模数 NTT 拆系数 FFT (MTT) 「学习笔记」FFT 之优化--NTT 前言 \(NT ...

  9. 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)

    再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...

随机推荐

  1. python基础练习题(题目 打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身)

    day8 --------------------------------------------------------------- 实例013:所有水仙花数 题目 打印出所有的"水仙花 ...

  2. FATAL: using recovery command file "recovery.conf" is not supported

    PostgreSQL12 附录 E. 版本说明 将recovery.conf设置移动到postgresql.conf中. (Masao Fujii, Simon Riggs, Abhijit Meno ...

  3. 基础学习:MYSQL命令大全(持续更新中---最近一次:2019.12.6)

    启动mysql : mysql -hlocalhost -uroot -p创建数据库:create database 数据库名字;指定要操作的数据库:use 数===据库名字;查看数据表建表语句:sh ...

  4. [STL] deque 双端队列

  5. Hadoop(一)Hadoop核心架构与安装

    Hadoop是什么 大白话,Hadoop是个存储数据,计算数据的分布式框架.核心组件是HDFS.MapReduce.Yarn. HDFS:分布式存储 MapReduce:分布式计算 Yarn:调度Ma ...

  6. 优化 Docker 镜像大小常见方法

    平时我们构建的 Docker 镜像通常比较大,占用大量的磁盘空间,随着容器的大规模部署,同样也会浪费宝贵的带宽资源.本文将介绍几种常用的方法来优化 Docker 镜像大小,这里我们使用 Docker ...

  7. OpenStack平台调度策略优化

    OpenStack平台报错分析 在OpenStack平台经历大并发的时候,比如同一个平台,大量的用户同时创建云主机(单个用户创建大量云主机不会触发此种现象),会达到云平台的性能瓶颈,导致创建云主机报错 ...

  8. 【PyHacker】编写WAF指纹探测与Sqlmap相结合

    使用Python编写探测WAF指纹脚本,再结合到Sqlmap中,这样以后再探测网站时,如果识别到此WAF指纹,就会显示出来.本文属于巡安似海PyHacker系列课程   编写探测识别WAF脚本 00x ...

  9. Hyperledger Fabric 核心概念

    一.说明 区块链是一个透明的,基于不可变模式的去中心化系统,核心就是一个分布式账本,记录网络上发生的所有交易. 区块链网络主要有三种类型:公共区块链.联盟区块链,以及私有区块链:我们熟知的比特币.以太 ...

  10. 697. Degree of an Array - LeetCode

    697. Degree of an Array - LeetCode Question 697. Degree of an Array - LeetCode Solution 理解两个概念: 数组的度 ...