「算法笔记」快速数论变换(NTT)

时间:2022-03-03 01:48:47

一、简介

前置知识:多项式乘法与 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)的更多相关文章

  1. 「算法笔记」快速傅里叶变换(FFT)

    一.引入 首先,定义多项式的形式为 \(f(x)=\sum_{i=0}^n a_ix^i\),其中 \(a_i\) 为系数,\(n\) 为次数,这种表示方法称为"系数表示法",一个 ...

  2. 【算法】快速数论变换&lpar;NTT&rpar;初探

    [简介] 快速傅里叶变换(FFT)运用了单位复根的性质减少了运算,但是每个复数系数的实部和虚部是一个余弦和正弦函数,因此系数都是浮点数,而浮点数的运算速度较慢且可能产生误差等精度问题,因此提出了以数论 ...

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

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

  4. Algorithm&colon; 多项式乘法 Polynomial Multiplication&colon; 快速傅里叶变换 FFT &sol; 快速数论变换 NTT

    Intro: 本篇博客将会从朴素乘法讲起,经过分治乘法,到达FFT和NTT 旨在能够让读者(也让自己)充分理解其思想 模板题入口:洛谷 P3803 [模板]多项式乘法(FFT) 朴素乘法 约定:两个多 ...

  5. 「算法笔记」树形 DP

    一.树形 DP 基础 又是一篇鸽了好久的文章--以下面这道题为例,介绍一下树形 DP 的一般过程. POJ 2342 Anniversary party 题目大意:有一家公司要举行一个聚会,一共有 \ ...

  6. 「算法笔记」2-SAT 问题

    一.定义 k-SAT(Satisfiability)问题的形式如下: 有 \(n\) 个 01 变量 \(x_1,x_2,\cdots,x_n\),另有 \(m\) 个变量取值需要满足的限制. 每个限 ...

  7. 「算法笔记」Polya 定理

    一.前置概念 接下来的这些定义摘自 置换群 - OI Wiki. 1. 群 若集合 \(s\neq \varnothing\) 和 \(S\) 上的运算 \(\cdot\) 构成的代数结构 \((S, ...

  8. JZYZOJ 2041 快速数论变换 NTT 多项式

    http://172.20.6.3/Problem_Show.asp?id=2041 https://blog.csdn.net/ggn_2015/article/details/68922404 代 ...

  9. &lbrack;快速数论变换 NTT&rsqb;

    先粘一个模板.这是求高精度乘法的 #include <bits/stdc++.h> #define maxn 1010 using namespace std; char s[maxn]; ...

随机推荐

  1. http 301和302的区别

    1.什么是301转向?什么是301重定向? 301转向(或叫301重定向,301跳转)是当用户或搜索引擎向网站服务器发出浏览请求时,服务器返回的HTTP数据流中头信息(header)中的状态码的一种, ...

  2. C盘空间不足,释放C盘空间

    最近电脑总是特别卡,后来发现C盘空间严重不足,只剩下几十兆,以前最严重的时候是剩下0kb可以,怎一个惨字了得... 我所知道的C盘空间不足会导致的几个主要问题有: 1)拷贝大文件会失败.因为拷贝和剪切 ...

  3. mysql 插入语句

    mysql 插入语句 什么时候用单引号,什么时候不用? 1.先创建一个表 create table user(username varchar(255),age int,marry boolean,b ...

  4. 原生Javascript实现图片轮播效果

    首先引入js运动框架 function getStyle(obj,name){ if(obj.currentStyle){ return obj.currentStyle[name]; } else{ ...

  5. Android -- 从源码带你从EventBus2&period;0飚到EventBus3&period;0(一)

    1,最近看了不少的面试题,不管是百度.网易.阿里的面试题,都会问到EventBus源码和RxJava源码,而自己只是在项目中使用过,却没有去用心的了解它底层是怎么实现的,所以今天就和大家一起来学习学习 ...

  6. Android SDK 开发——发布使用踩坑之路

    前言 在 Android 开发过程中,有些功能是通用的,或者是多个业务方都需要使用的. 为了统一功能逻辑及避免重复开发,因此将该功能开发成一个 SDK 是相当有必要的. 背景 刚好最近自己遇到了类似需 ...

  7. Linux测试硬盘读性能的常用工具-hdparm和dd俩搭档

    Linux测试硬盘读性能的常用工具-hdparm和dd俩搭档 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.hparm        # 它用来在基于 Linux的系统上获取或 ...

  8. (转)RBAC权限模型——项目实战

    一.前言 权限一句话来理解就是对资源的控制,对web应用来说就是对url的控制,关于权限可以毫不客气的说几乎每个系统都会包含,只不过不同系统关于权限的应用复杂程序不一样而已,现在我们在用的权限模型基本 ...

  9. VUE 安装&amp&semi;创建一个项目

    1,安装node.js vue依赖nodejs,所以首先要安装node.js 然后打开cmd,输入命令, node -v.正常出现版本号,说明你已经安装成功了 下载地址:http://nodejs.c ...

  10. &lbrack;硬件&rsqb;&lowbar;ELVE&lowbar;STLINK下载出现nternal command error问题

    我之前也出现过这个这个,然后折腾一晚上,升级什么都都不好使 最后我换了一根短的线,回归正常!!!