任意模数ntt_【模板篇】NTT和三模数NTT

之前写过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;<

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值