NTT 的三次变八次优化
就是将 NTT 的域扩到复数。
我不知道高斯整数的其他取模方式,所以巨慢/xk。而且没用。
我们知道高斯整数的神秘取模方式,使得其结果的范数小于除数的一半。然而我们发现这个取模在整数下的结果仍然在整数取模的同余系中!
好很有精神!
我们选取 ,我们只需要验证 。就大功告成啦!
然后我们写一个这样的程序:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=998244353;
signed main(){
ios::sync_with_stdio(0);
int g=1,p=-1;
for(int i=1;i<=(mod-1)/2;i++){
g=g*3;
int op=round(1.0*g/mod);
g=g-mod*op;
p=p*3;
op=round(1.0*p/mod);
p=p-mod*op;
assert(g==-p);
// assert(g>0);
}
cout<<g<<" "<<p;
return 0;
}
跑出来没有 RE!好!
于是理论上 NTT 可以扩域到高斯整数。然后就可以用类似于 FFT 的三次变两次优化啦!
然后写一发,中间我都不知道我写了什么神秘东西,然后它 TLE 啦!
说实话,它是正确的我都很惊讶,于是我更有兴趣了。
注意到这里我直接用 __int128
为了在高斯整数运算的时候不会出现溢出。
然后我们直接写一个全部取模的版本:
它居然也是正确的!!!
过于神秘了。
然后我就不想写了,因为验证这个东西是正确的就已经达到我的目的了,过于神秘了还是。
然后我转念一想,我不是全部取模了吗?那我直接启动原神!把高斯整数的取模直接删掉!
它过了。
????????
然后我把乘法里面的那个取模删掉,它快了 0.4s!!!
这个时候它的效率就和我第一版 NTT 的效率差不多了。
说实话,它能表现成这样,无论是它的正确性或者速度就已经很令我震惊了。
最后那个在 NTT 中只有两层取模的那个优化我就不加了。
现在这个东西就根本不是高斯整数了,就是只是在实部和虚部这两个东西里直接取模,它居然是正确的/xk。
所以虚数神通广大!
本文作者:xingyu_xuan
本文链接:https://www.cnblogs.com/xingyuxuan/p/18146779
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步