之前写过FFT的笔记. 我们知道FFT是在复数域上进行的变换.

而且经过数学家的证明, DFT是复数域上唯一满足循环卷积性质的变换.

而我们在OI中, 经常遇到对xxxx取模的题目, 这就启发我们可不可以在模运算的意义下找一个这样的变换.

然后我们发现有个神奇的东西, 原根\(g\), 这东西在模意义下相当于单位复根\(-e^{\frac{2\pi i}{n}}\).

所以我们预处理一下\(g\)的幂和逆元, 然后改一下fft的代码就出现了快速数论变换ntt

懒得写了 直接上代码:

void getwn(){ //预处理原根的幂和逆元

int x=qpow(3,p-2);

for(int i=0;i<20;++i){

wn[i]=qpow(3,(p-1)/(1<

inv[i]=qpow(x,(p-1)/(1<

}

}

void ntt(int *y,bool f){ rev(y); //翻转代码和fft无异

for(int m=2,id=1;m<=n;m<<=1,++id){ //id用来记录转到第几下了

for(int k=0;k

int w=1,wm=f?wn[id]:inv[id]; //如果是dft就用幂, idft就用幂的逆元

for(int j=0;j

//这里跟fft一样, 不过要对p取模

int u=y[k+j]%p,t=1ll*w*y[k+j+m/2]%p;

y[k+j]=u+t; if(y[k+j]>p) y[k+j]-=p;

y[k+j+m/2]=u-t; if(y[k+j+m/2]<0) y[k+j+m/2]+=p;

w=1ll*w*wm%p;

}

}

}

if(!f){

int x=qpow(n,p-2);

for(int i=0;i

y[i]=1ll*y[i]*x%p;

}

}

好像差不多呢~ 不过这样就要求我们找一个原根好求的数. 比如著名的uoj数: 998244353 还有1004535809和469762049等, 这三个数原根都是3~

好像因为当时一看到模数不是1e9+7一般就会想到ntt, vfk为了防止这一点, 模数统一采用998244353, 现在看看收效不错.

不过 有些丧心病狂的人就是要用1e9+7作为ntt的模数, 甚至还出现了可以不模质数的情况!

那我们怎么解决任意模数ntt呢? 我们可以采用拆系数ntt或者三模数ntt. 这里介绍一下三模数ntt.

对于一般的数据范围, \(n\leq10^5, a_i\leq10^9\), 这样可能会到10^5*10^{9^2}=10^{23}级别.

所以我们可以找三个乘积\(>10^{23}\)的ntt-friendly的数, 然后分别ntt再想办法合并.

我们假如答案是ans, 那我们做三次ntt后就能得到如下三个柿子.

\[

\left\{\begin{matrix}

ans\equiv a_1(\mod m_1)\\

ans\equiv a_2(\mod m_2)\\

ans\equiv a_3(\mod m_3)

\end{matrix}\right.

\]

我们把前两个柿子通过中国剩余定理合并, 就可以得到

\[

\left\{\begin{matrix}

ans\equiv A(\mod M)\\

ans\equiv a_3(\mod m_3)

\end{matrix}\right.

\]

其中, \(M=m_1*m_2\)

这样我们设\(ans=kM+A\),

\[

kM+A\equiv a_3(\mod m_3) \k=(a_3-A)*M^{-1} (\mod m_3)

\]

这样我们求出\(k\)然后代回到\(ans=kM+A\)就可以求对任意模数取模的结果了.

中国剩余定理合并的时候直接乘是可以爆long long的, 所以我们要用到\(O(1)\)快速乘~

下面上一波代码: luogu4245 【模板】MTT

哎呀觉得自己码风有点丑啊qwq

#include

#include

#include

typedef long long LL;

const int N=600020,p0=469762049,p1=998244353,p2=1004535809;

const LL M=1ll*p0*p1;

int wn[20],nw[20],rev[N],n,lg,p;

int qpow(int a,int b,int p,int s=1){

for(;b;b>>=1,a=1ll*a*a%p)

if(b&1) s=1ll*s*a%p;

return s;

}

LL mul(LL a,LL b,LL p){ a%=p; b%=p;

return (a*b-(LL)((long double)a*b/p)*p+p)%p;

}

void calcw(int p){

int x=qpow(3,p-2,p);

for(int i=0;i<20;++i){

wn[i]=qpow(3,(p-1)/(1<

nw[i]=qpow(x,(p-1)/(1<

}

}

void init(){

for(int i=0;i

rev[i]=(rev[i>>1]>>1)|((i&1)<

}

void ntt(int *y,bool f,int p){ calcw(p);

for(int i=0;i

for(int m=2,id=1;m<=n;m<<=1,++id){

for(int k=0;k

int w=1,wm=f?wn[id]:nw[id];

for(int j=0;j>1;++j){

int &a=y[k+j]; int &b=y[k+j+m/2];

int u=a%p,t=1ll*w*b%p;

a=u+t; if(a>p) a-=p;

b=u-t; if(b<0) b+=p;

w=1ll*w*wm%p;

}

}

} int x=qpow(n,p-2,p);

if(!f) for(int i=0;i

}

char c1[N],c2[N]; int a[N],b[N],c[N],d[N],ans[3][N];

int main(){

int l1,l2; scanf("%d%d%d",&l1,&l2,&p);

for(int i=0;i<=l1;++i) scanf("%d",&a[i]),a[i]%=p;

for(int i=0;i<=l2;++i) scanf("%d",&b[i]),b[i]%=p;

for(n=1;n

std::copy(a,a+n,c); std::copy(b,b+n,d);

ntt(c,1,p0); ntt(d,1,p0);

for(int i=0;i

std::copy(a,a+n,c); std::copy(b,b+n,d);

ntt(c,1,p1); ntt(d,1,p1);

for(int i=0;i

std::copy(a,a+n,c); std::copy(b,b+n,d);

ntt(c,1,p2); ntt(d,1,p2);

for(int i=0;i

ntt(ans[0],0,p0); ntt(ans[1],0,p1); ntt(ans[2],0,p2);

for(int i=0;i

LL A=mul(1ll*ans[0][i]*p1%M,qpow(p1%p0,p0-2,p0),M)

+mul(1ll*ans[1][i]*p0%M,qpow(p0%p1,p1-2,p1),M);

if(A>M) A-=M;

LL k=((ans[2][i]-A)%p2+p2)%p2*qpow(M%p2,p2-2,p2)%p2;

a[i]=1ll*(k%p)*(M%p)%p+A%p;

if(a[i]>p) a[i]-=p;

}

for(int i=0;i<=l1+l2;++i) printf("%d",a[i]);

}

原文:https://www.cnblogs.com/enzymii/p/8925992.html

任意模数ntt_【模板篇】NTT和三模数NTT相关推荐

  1. 洛谷.4245.[模板]任意模数NTT(MTT/三模数NTT)

    题目链接 三模数\(NTT\): 就是多模数\(NTT\)最后\(CRT\)一下...下面两篇讲的都挺明白的. https://blog.csdn.net/kscla/article/details/ ...

  2. 任意模数ntt_【知识总结】多项式全家桶(三)(任意模数NTT)

    经过两个月的咕咕,"多项式全家桶" 系列终于迎来了第三期--(雾) 先膜拜(伏地膜)大恐龙的博客:任意模数 NTT (在页面右侧面板 "您想嘴谁" 中选择 &q ...

  3. 洛谷P4245:【模板】MTT (CRT+三模数NTT)

    题目传送门:https://www.luogu.org/problemnew/show/P4245 题目分析:一道任意模数多项式乘法的模板题.可以写拆项+FFT,或者三模数NTT.我暂时只写了后者. ...

  4. 任意模数ntt_任意模数NTT

    任意模数\(NTT\) 众所周知,为了满足单位根的性质,\(NTT\)需要质数模数,而且需要能写成\(a2^{k} + 1\)且\(2^k \ge n\) 比较常用的有\(998244353,1004 ...

  5. [Qt教程] 第33篇 网络(三)FTP(一)

    [Qt教程] 第33篇 网络(三)FTP(一) 楼主  发表于 2013-9-4 14:52:46 | 查看: 392| 回复: 8 FTP(一) 版权声明 该文章原创于作者yafeilinux,转载 ...

  6. [Qt教程] 第43篇 进阶(三)对象树与拥有权

    [Qt教程] 第43篇 进阶(三)对象树与拥有权 楼主  发表于 2013-9-12 16:39:33 | 查看: 255| 回复: 1 对象树与拥有权 版权声明 该文章原创于Qter开源社区 导语 ...

  7. 10-C++远征之模板篇-学习笔记

    C++远征之模板篇 本文及代码收录于个人编程笔记(整理中,欢迎Star): https://github.com/mtianyan/Programming-Notebook 将会学到的内容: 模板函数 ...

  8. 《深入浅出WPF》笔记——模板篇

    原文:<深入浅出WPF>笔记--模板篇 我们通常说的模板是用来参照的,同样在WPF中,模板是用来作为制作控件的参照. 一.认识模板 1.1WPF菜鸟看模板 前面的记录有提过,控件主要是算法 ...

  9. 他是第一个到达学校的人英语_日本留学:不需要英语成绩的大学盘点·私立学部篇(第三弹)...

    今日知识点:日本留学也是需要英语成绩的. 很多同学左脚刚要迈进日本留学大门,右脚就被英语成绩给吓回去了.嗯?我就是因为英语不好,才来日本的呀??? 连载篇来啦~大圣历时168小时整理出来不需要提交英语 ...

最新文章

  1. EditText中的几个常用属性
  2. 完美解决latex警告信息:Citation `Gusfield:97‘ on page 1 undefined.
  3. HyperlinkButton——WP8控件学习
  4. node学习准备工作1 --- nvm下载、终端环境iterm2配置
  5. 《阿里巴巴 Java 开发手册》读书笔记
  6. chkconfig的用法
  7. 传统生成API文档弊端
  8. ABB 机器人 添加多任务
  9. spring mvc重定向_Spring的Web MVC –重定向到内存泄漏
  10. 【LeetCode笔记】剑指 Offer 93. 复原 IP 地址(Java、DFS、字符串)
  11. 解决压缩包跨平台解压缩的中文乱码问题
  12. Spring映射器、适配器、解析器
  13. Go语言(Golang)超时机制
  14. 加拿大政府贯彻量子技术重要性,221万美元资助量子算法研究所
  15. 收藏 | 42 款 Chrome 插件神器,你必须知道!
  16. m利用SIMILINK仿真模块实现多径信道的动态仿真模拟
  17. 数据时代的的企业管理 记SAP商业同略会
  18. php 时间戳 周几,php时间戳怎么转换星期
  19. android qt 对比_Qt for Android 开发大坑
  20. 毕业设计 单片机(stm32)远程宠物喂养系统 - 物联网 esp8266

热门文章

  1. 使用CloudCompare渲染好看的油麦菜点云的小方法
  2. C#酒店会员管理系统
  3. (zt) ipad 使用技巧整理
  4. 卡塔尔世界杯--程序员的诗和远方
  5. 这款小程序 能让你和孙悟空一样 可以七十二变
  6. python爬取b站弹幕分析_Python 爬取「后浪」弹幕,看看大家都在说什么
  7. 孙浩北大计算机,周耀山工作简报第53期——清华北大高材生黎明、孙浩在白河高级中学学法座谈会成功举行...
  8. windows11 任务栏和开始菜单都不见了怎么办?
  9. XiaoHu是什么?(介绍帖)
  10. @EnableConfigurationProperties 注解