「算法笔记」快速数论变换(NTT)
一、简介
前置知识:多项式乘法与 FFT。
FFT 涉及大量 double
类型数据操作和 \(\sin,\cos\) 运算,会产生误差。快速数论变换(Number Theoretic Transform,简称 NTT)在 FFT 的基础上,优化了常数及误差。
NTT 其实就是把 FFT 中的单位根换成了原根。
NTT 解决的是多项式乘法带模数的情况,可以说有些受模数的限制,多项式系数应为整数。
二、原根 与 NTT
「算法笔记」基础数论 2 中提及了原根的部分内容。
对于质数 \(p\),若 \(g\) 为 \(p\) 的原根,则 \(g^i\bmod p\,(0\leq i<p)\) 互不相同。
考虑可以表示为 \(p=a\cdot 2^k+1\) 的质数 \(p\)。NTT 的模数一般选取这样符合要求的 \(p\)。比较常见的 \(p\) 有 \(998244353=119\cdot 2^{23}+1\)、\(1004535809=479\cdot 2^{21}+1\),它们的原根都是 \(3\)。
NTT 与 FFT 几乎一样,只不过 FFT 中代入的是 \(\omega_n^k\),而 NTT 中代入的是 \({(g^{\frac{p-1}{n}})}^k\)。
\({(g^{\frac{p-1}{n}})}^k\) 满足 FFT 中所用到的 \(\omega_n^k\) 拥有的性质。
结论:\(\omega_n^k\equiv {(g^{\frac{p-1}{n}})}^k\pmod p\),可以把 \({(g^{\frac{p-1}{n}})}^k\) 看成是 \(\omega_n^k\) 的等价。证明略。
由于 \(p\) 可以表示为 \(p=a\cdot 2^k+1\) 的形式,并且多项式项数 \(n\) 已被我们补为 \(2\) 的幂次,所以 \(\frac{p-1}{n}\) 一定为整数(注意 \(n\leq 2^k\),不然会出问题)。
代码只需在 FFT 的基础上稍作修改即可。复杂度同样为 \(\mathcal{O}(n\log n)\)。
- //Luogu P3803
- #include<bits/stdc++.h>
- #define int long long
- using namespace std;
- const int N=3e6+5,mod=998244353;
- int n,m,a[N],b[N],len,r[N],inv;
- int mul(int x,int n,int mod){
- int ans=mod!=1;
- for(x%=mod;n;n>>=1,x=x*x%mod)
- if(n&1) ans=ans*x%mod;
- return ans;
- }
- void NTT(int a[N],int n,int opt){ //opt=1/-1: DFT/IDFT
- for(int i=0;i<n;i++)
- if(i<r[i]) swap(a[i],a[r[i]]);
- for(int k=2;k<=n;k<<=1){
- int m=k>>1,x=mul(3,(mod-1)/k,mod),w=1,v;
- if(opt==-1) x=mul(x,mod-2,mod);
- for(int i=0;i<n;i+=k,w=1)
- for(int j=i;j<i+m;j++) v=w*a[j+m]%mod,a[j+m]=(a[j]-v+mod)%mod,a[j]=(a[j]+v)%mod,w=w*x%mod;
- }
- if(opt==-1){
- inv=mul(len,mod-2,mod);
- for(int i=0;i<n;i++) a[i]=a[i]*inv%mod;
- }
- }
- signed main(){
- scanf("%lld%lld",&n,&m);
- for(int i=0;i<=n;i++)
- scanf("%lld",&a[i]);
- for(int i=0;i<=m;i++)
- scanf("%lld",&b[i]);
- n=n+m+1;
- for(len=1;len<n;len<<=1);
- for(int i=0;i<len;i++)
- r[i]=(r[i>>1]>>1)|((i&1)?len>>1:0);
- NTT(a,len,1),NTT(b,len,1);
- for(int i=0;i<len;i++) a[i]=a[i]*b[i]%mod;
- NTT(a,len,-1);
- for(int i=0;i<n;i++)
- printf("%lld%c",a[i],i==n-1?'\n':' ');
- return 0;
- }
Update:改了改后的板子→link。
「算法笔记」快速数论变换(NTT)的更多相关文章
- 「算法笔记」快速傅里叶变换(FFT)
一.引入 首先,定义多项式的形式为 \(f(x)=\sum_{i=0}^n a_ix^i\),其中 \(a_i\) 为系数,\(n\) 为次数,这种表示方法称为"系数表示法",一个 ...
- 【算法】快速数论变换(NTT)初探
[简介] 快速傅里叶变换(FFT)运用了单位复根的性质减少了运算,但是每个复数系数的实部和虚部是一个余弦和正弦函数,因此系数都是浮点数,而浮点数的运算速度较慢且可能产生误差等精度问题,因此提出了以数论 ...
- 「学习笔记」FFT 之优化——NTT
目录 「学习笔记」FFT 之优化--NTT 前言 引入 快速数论变换--NTT 一些引申问题及解决方法 三模数 NTT 拆系数 FFT (MTT) 「学习笔记」FFT 之优化--NTT 前言 \(NT ...
- Algorithm: 多项式乘法 Polynomial Multiplication: 快速傅里叶变换 FFT / 快速数论变换 NTT
Intro: 本篇博客将会从朴素乘法讲起,经过分治乘法,到达FFT和NTT 旨在能够让读者(也让自己)充分理解其思想 模板题入口:洛谷 P3803 [模板]多项式乘法(FFT) 朴素乘法 约定:两个多 ...
- 「算法笔记」树形 DP
一.树形 DP 基础 又是一篇鸽了好久的文章--以下面这道题为例,介绍一下树形 DP 的一般过程. POJ 2342 Anniversary party 题目大意:有一家公司要举行一个聚会,一共有 \ ...
- 「算法笔记」2-SAT 问题
一.定义 k-SAT(Satisfiability)问题的形式如下: 有 \(n\) 个 01 变量 \(x_1,x_2,\cdots,x_n\),另有 \(m\) 个变量取值需要满足的限制. 每个限 ...
- 「算法笔记」Polya 定理
一.前置概念 接下来的这些定义摘自 置换群 - OI Wiki. 1. 群 若集合 \(s\neq \varnothing\) 和 \(S\) 上的运算 \(\cdot\) 构成的代数结构 \((S, ...
- JZYZOJ 2041 快速数论变换 NTT 多项式
http://172.20.6.3/Problem_Show.asp?id=2041 https://blog.csdn.net/ggn_2015/article/details/68922404 代 ...
- [快速数论变换 NTT]
先粘一个模板.这是求高精度乘法的 #include <bits/stdc++.h> #define maxn 1010 using namespace std; char s[maxn]; ...
随机推荐
- 学习java的第十天
一.今日收获 1.java完全学习手册第二章2.9程序流程控制中的选择结构与顺序结构的例题 2.观看哔哩哔哩上的教学视频 二.今日问题 1.例题的问题不大,需要注意大小写,新的语句记忆不牢 2.哔哩哔 ...
- day03 Django目录结构与reques对象方法
day03 Django目录结构与reques对象方法 今日内容概要 django主要目录结构 创建app注意事项(重点) djago小白必会三板斧 静态文件配置(登录功能) requeste对象方法 ...
- 在 Qualys SSL Labs SSL 测试中获得 A+ 评级的秘技 2021 版
本系列文章将阐述主流应用交付控制器和主流 Web 服务器如何运行 HTTP/2 和 TLSv1.3 协议,以及如何在 SSL Test 中获得 A+ 评级. 请访问原文链接:https://sysin ...
- [php安全]原生类的利用
php原生类的利用 查看原生类中具有魔法函数的类 $classes = get_declared_classes(); foreach ($classes as $class) { $methods ...
- 详解 java 异常
Throwable 可以用来表示任何可以作为异常抛出的类(注意,是类不是接口),分为两种: Error(注意!error也是可以throw的,但是不建议) 和 Exception. 其中 Error ...
- 一行配置搞定 Spring Boot项目的 log4j2 核弹漏洞!
相信昨天,很多小伙伴都因为Log4j2的史诗级漏洞忙翻了吧? 看到群里还有小伙伴说公司里还特别建了800+人的群在处理... 好在很快就有了缓解措施和解决方案.同时,log4j2官方也是速度影响发布了 ...
- Redis监控参数
目录 一.客户端 二.服务端 一.客户端 127.0.0.1:6379> info stats #Redis自启动以来处理的客户端连接数总数 total_connections_received ...
- df和du显示不同
目录 一.简介 二.原因分析 三.解决方法 一.简介 Linux服务器,使用df -h查看文件系统使用率,可以看到/dev/xvdb1磁盘占用了约27G,挂载目录为/opt. 但进入到opt目录中执行 ...
- array_filter()用法
第一种情况: 通过函数,过滤数组中的元素 array_filter($arr,'函数名称') 函数里可以写相应的过滤原则,下面举个栗子,过滤掉不是数字的元素 $arr=array('a','b','c ...
- .NET内存性能分析宝典
.NET Memory Performance Analysis 知道什么时候该担心,以及在需要担心的时候该怎么做 译者注 **作者信息:Maoni Stephens ** - 微软架构师,负责.NE ...