FFTFFTFFT有时候会被卡精度?所以可能会有模数,有了模数以后就需要模数的原根。

原根是什么?(留坑待填)

NTTNTTNTT有很多种解决方法
1.1.1.特殊模数
(2k+1)∣(p−1),(p−1)>DFT的长度(2k+1)|(p−1),(p−1)>DFT的长度(2k+1)∣(p−1),(p−1)>DFT的长度,可以直接暴力求原根ggg,用ggg代替单位复数根

2.2.2.一般模数

  • 三模数法(9次DFT)
    如果这个模数的原根不好求,而模数又很大,可以用三个模数
    要求 mod1×mod2×mod3≥n×p2mod1\times mod2\times mod3\ge n\times p^2mod1×mod2×mod3≥n×p2
    常用998244353,1004535809,469762049998244353,1004535809,469762049998244353,1004535809,469762049,因为他们的原根都是333
    对这几个模数分别做DFTDFTDFT,然后用中国剩余定理合并,然后对原模数取模即可
    中国剩余定理部分
    ans≡c1modm1ans\equiv c1\ mod\ m1ans≡c1 mod m1
    ans≡c2modm2ans\equiv c2\ mod\ m2ans≡c2 mod m2
    ans≡c3modm3ans\equiv c3\ mod\ m3ans≡c3 mod m3
    如果直接合并的话会爆longlonglong\ longlong long,可以先合并两个,再用奇技淫巧合并第三个
    合并前两个:
    ans≡(c1×m2×inv(m2,m1)+c2×m1×inv(m1,m2))mod(m1×m2)ans\equiv (c1\times m2\times inv(m2,m1)+c2\times m1\times inv(m1,m2)) mod\ (m1\times m2)ans≡(c1×m2×inv(m2,m1)+c2×m1×inv(m1,m2))mod (m1×m2)
    其中inv(x,y)inv(x,y)inv(x,y)表示xxx对yyy取模的逆元。
    把上式化简为ans≡CmodMans\equiv C\ mod\ Mans≡C mod M
    设ans=x×M+C=y×m3+c3ans=x\times M+C=y\times m3+c3ans=x×M+C=y×m3+c3
    接下来很重要:求出xmodm3x\ mod\ m3x mod m3意义下的值:
    x≡(c3−C)×M−1modm3x\equiv (c3-C)\times M^{-1}\ mod\ m3x≡(c3−C)×M−1 mod m3
    这样就可以算出右半部分的值qqq,令x=k×m3+qx=k\times m3+qx=k×m3+q,代入ansansans得:
    ans=k×m1×m2×m3+q×M+Cans=k\times m1\times m2\times m3+q\times M+Cans=k×m1×m2×m3+q×M+C
    因为ans∈[0,m1×m2×m3)ans\in [0,m1\times m2\times m3)ans∈[0,m1×m2×m3),所以k=0k=0k=0,于是ansansans就可直接计算。
    做9次DFT,常数极大
    有一道模板题luogu4245
    直接用三模数法,代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define LL long long
#define maxn 400005
using namespace std;
const LL mod1=998244353,mod2=1004535809,mod3=469762049,g=3;
const LL M=1LL*mod1*mod2;inline int rd(){int x=0,f=1;char c=' ';while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();return x*f;
}int n,m,p,rev[maxn],limit=1,l;
LL a[3][maxn],b[3][maxn],ans[maxn];inline LL mul(LL x,int k,LL MOD){LL ret=0;while(k){if(k&1) (ret+=x)%=MOD;(x+=x)%=MOD; k>>=1;} return ret%MOD;
}inline LL qpow(LL x,int k,int MOD){LL ret=1;while(k){if(k&1) ret=ret*x%MOD;x=x*x%MOD; k>>=1;} return ret%MOD;
}inline void NTT(LL *F,int type,int MOD){for(int i=0;i<limit;i++){F[i]%=MOD;if(i<rev[i]) swap(F[i],F[rev[i]]);}for(int mid=1;mid<limit;mid<<=1){LL Wn=qpow(g,type==1?(MOD-1)/(mid<<1):(MOD-1-(MOD-1)/(mid<<1)),MOD);//!for(int r=mid<<1,j=0;j<limit;j+=r){LL w=1;for(int k=0;k<mid;k++,w=w*Wn%MOD){LL x=F[j+k],y=w*F[j+mid+k]%MOD;F[j+k]=(x+y)%MOD; F[j+mid+k]=(x-y+MOD)%MOD;}}}if(type==-1){LL INV=qpow(limit,MOD-2,MOD);//除以limitfor(int i=0;i<limit;i++) F[i]=F[i]*INV%MOD; }
}inline void CRT(){for(int i=0;i<limit;i++){LL tmp=0;(tmp+=mul(a[0][i]*mod2%M,qpow(mod2,mod1-2,mod1),M))%=M;(tmp+=mul(a[1][i]*mod1%M,qpow(mod1,mod2-2,mod2),M))%=M;a[1][i]=tmp;}for(int i=0;i<limit;i++){//x=(c3-C)/M mod mod3LL tmp=(a[2][i]-a[1][i]%mod3+mod3)%mod3*qpow(M%mod3,mod3-2,mod3)%mod3;ans[i]=(M%p*tmp%p+a[1][i]%p)%p;}
}inline void solve(int x,int MOD){NTT(a[x],1,MOD); NTT(b[x],1,MOD);for(int i=0;i<limit;i++) a[x][i]=a[x][i]*b[x][i]%MOD;NTT(a[x],-1,MOD);
}int main(){n=rd(); m=rd(); p=rd();for(int i=0;i<=n;i++){int x=rd();for(int j=0;j<3;j++) a[j][i]=x%p;}for(int i=0;i<=m;i++){int x=rd();for(int j=0;j<3;j++) b[j][i]=x%p;}while(limit<=n+m) limit<<=1,++l;for(int i=0;i<limit;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));solve(0,mod1); solve(1,mod2); solve(2,mod3);CRT();for(int i=0;i<=n+m;i++) printf("%lld ",ans[i]);return 0;
}
  • 拆系数法(7次DFT)
    将两个多项式系数拆开,然后发现可以分成三部分计算,不很常用而且精度掉的厉害,这里先不做详细解释

  • MTT(4次DFT)
    奇技淫巧,话说三模数NTT卡卡常多预处理一些应该都能过去,不行就开O2,跑的蛮快的(反正省选也开O2 ),这个东西先放着,以后闲得没事 再来看

任意模数NTT(学习笔记)相关推荐

  1. 任意模数NTT(MTT)

    前言 众所周知,NTT有几个经典的模数:469762049,998244353,1004535809469762049,998244353,1004535809469762049,998244353, ...

  2. 洛谷 P4245 【模板】任意模数NTT

    洛谷 P4245 [模板]任意模数NTT 贴个板子,4次DFT. Code #include<cstdio> #include<algorithm> #include<c ...

  3. 任意模数ntt_MTT:任意模数NTT

    MTT:任意模数NTT 概述 有时我们用FFT处理的数据很大,而模数可以分解为\(a\cdot 2^k+1\)的形式.次数用FFT精度不够,用NTT又找不到足够大的模数,于是MTT就应运而生了. MT ...

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

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

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

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

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

    经过两个月的咕咕,"多项式全家桶" 系列终于迎来了第三期--(雾) 上一篇:[知识总结]多项式全家桶(二)(ln和exp) 先膜拜(伏地膜)大恐龙的博客:任意模数 NTT (在页面 ...

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

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

  8. P4245 【模板】任意模数NTT

    Luogu4245 只要做三次的NTT,快的飞起 普通NTT,做9次 #include<cstdio> #include<cstring> #include<iostre ...

  9. Power oj 2781: 上决╇ф的黑科技 (任意模数NTT|拆系数FFT)

    https://www.oj.swust.edu.cn/problem/show/2781 式子很好推 很明显卷积即可 可以使用 NTT或者拆系数FFT 这里使用的是NTT #include < ...

最新文章

  1. freebasic 编译linux,免费BASIC编译器下载
  2. 将服务器文件加载至hive表中,Hive入门到剖析(四)
  3. 编码规范 | Java函数优雅之道(上)
  4. ajax应用_AJAX的应用
  5. 容器编排技术 -- Kubernetes kubectl create service 命令详解
  6. WCF在安全性方面的支持(1):一些概念
  7. Python打印指定日期日历
  8. [OC]TableView使用
  9. 【Linux 命令学习第二天】
  10. cemtos7重置mysql root,Centos7重置MySQL8.0 root密码
  11. 这份字节、阿里内部秘传的面经,被我搞到手了……
  12. 一款好看的pycharm主题Atom One Dark
  13. Python超市商品管理系统
  14. 美国防部应改进人工智能战略和加强协作指导
  15. 连接微信运动服务器忙,为啥微信运动突然不计步了(只需一招问题立马解决)...
  16. Rasa 3.x 学习系列- 内网环境部署Docker及Rasa duckling、Redis
  17. python角谷猜想递归实现_第三周函数的递归---编程作业: 递归编程练习
  18. 最小二乘法和主成分分析的比较 matlab  儿子的papa
  19. 项目需求分析(那周余嘉熊掌将得队)
  20. python——线性回归实例实战

热门文章

  1. java 文件解压缩zip_java解压缩zip文件
  2. 视频编码h264怎么看_你所要知道的音视频--04
  3. Scratch基础教学之孙悟空的吹毛变猴
  4. 冲量在线要做数据流通基础设施服务商
  5. Ubuntu 版本的命名规则和开发代号
  6. 数据智能的本质和技术体系要求
  7. Mac磁盘分析工具ncdu使用
  8. JavaScript判断当前浏览器是否为IE或者Edge
  9. RabbitMQ 延迟队列详解
  10. 《C语言小程序篇---1》——实现一个“富婆通讯录“(超详细)