任意模数\(NTT\)

众所周知,为了满足单位根的性质,\(NTT\)需要质数模数,而且需要能写成\(a2^{k} + 1\)且\(2^k \ge n\)

比较常用的有\(998244353,1004535809,469762049\),这三个原根都是\(3\)

如果要任意模数怎么办?

\(n\)次多项式在模\(m\)下乘积,最终系数一定不会大于\(nm^2\)

所以我们找三个模数分别做\(NTT\)再合并一下就好辣

但这样的合并结果会爆\(long long\)呢

需要用高精吗?

可以使用一些技巧

我们要合并的是

\[\left \{
\begin{aligned}
x \equiv a_1 \pmod {m_1} \\
x \equiv a_2 \pmod {m_2} \\
x \equiv a_3 \pmod {m_3} \\
\end{aligned}
\right.
\]

我们先在\(long long\)范围内合并前两个

\[\left \{
\begin{aligned}
x \equiv A \pmod M \\
x \equiv a_3 \pmod {m_3} \\
\end{aligned}
\right.
\]

由于最后结果模\(M\)为\(A\),模\(m_3\)为\(a_3\)

设最后的答案是

\[ans = kM + A
\]

且\(k\)需要满足

\[kM + A \equiv a_3 \pmod {m_3}
\]

所以\(k\)一定是在模\(m_3\)意义下求出的,为

\[k \equiv (a_3 - A)M^{-1} \pmod {m_3}
\]

求出\(k\)后就可以直接在原模数意义下求出

\[ans = kM + A
\]

在第一次合并的时候需要快速乘

做三次\(NTT\)常数有够大的

模板题

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define cls(s,v) memset(s,v,sizeof(s))
#define mp(a,b) make_pair<int,int>(a,b)
#define cp pair<int,int>
using namespace std;
const int maxn = 400005,maxm = 100005,INF = 0x3f3f3f3f;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = 0; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 1) + (out << 3) + c - 48; c = getchar();}
return flag ? out : -out;
}
int pr[]={469762049,998244353,1004535809};
int R[maxn];
inline LL qpow(LL a,LL b,LL p){
LL re = 1; a %= p;
for (; b; b >>= 1,a = a * a % p)
if (b & 1) re = re * a % p;
return re;
}
struct FFT{
int G,P,A[maxn];
void NTT(int* a,int n,int f){
for (int i = 0; i < n; i++) if (i < R[i]) swap(a[i],a[R[i]]);
for (int i = 1; i < n; i <<= 1){
int gn = qpow(G,(P - 1) / (i << 1),P);
for (int j = 0; j < n; j += (i << 1)){
int g = 1,x,y;
for (int k = 0; k < i; k++,g = 1ll * g * gn % P){
x = a[j + k],y = 1ll * g * a[j + k + i] % P;
a[j + k] = (x + y) % P,a[j + k + i] = (x + P - y) % P;
}
}
}
if (f == 1) return;
int nv = qpow(n,P - 2,P); reverse(a + 1,a + n);
for (int i = 0; i < n; i++) a[i] = 1ll * a[i] * nv % P;
}
}fft[3];
int F[maxn],G[maxn],B[maxn],deg1,deg2,deg,md;
LL ans[maxn];
LL inv(LL n,LL p){return qpow(n % p,p - 2,p);}
LL mul(LL a,LL b,LL p){
LL re = 0;
for (; b; b >>= 1,a = (a + a) % p)
if (b & 1) re = (re + a) % p;
return re;
}
void CRT(){
deg = deg1 + deg2;
LL a,b,c,t,k,M = 1ll * pr[0] * pr[1];
LL inv1 = inv(pr[1],pr[0]),inv0 = inv(pr[0],pr[1]),inv3 = inv(M % pr[2],pr[2]);
for (int i = 0; i <= deg; i++){
a = fft[0].A[i],b = fft[1].A[i],c = fft[2].A[i];
t = (mul(a * pr[1] % M,inv1,M) + mul(b * pr[0] % M,inv0,M)) % M;
k = ((c - t % pr[2]) % pr[2] + pr[2]) % pr[2] * inv3 % pr[2];
ans[i] = ((k % md) * (M % md) % md + t % md) % md;
}
}
void conv(){
int n = 1,L = 0;
while (n <= (deg1 + deg2)) n <<= 1,L++;
for (int i = 1; i < n; i++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));
for (int u = 0; u <= 2; u++){
fft[u].G = 3; fft[u].P = pr[u];
for (int i = 0; i <= deg1; i++) fft[u].A[i] = F[i];
for (int i = 0; i <= deg2; i++) B[i] = G[i];
for (int i = deg2 + 1; i < n; i++) B[i] = 0;
fft[u].NTT(fft[u].A,n,1); fft[u].NTT(B,n,1);
for (int i = 0; i < n; i++) fft[u].A[i] = 1ll * fft[u].A[i] * B[i] % pr[u];
fft[u].NTT(fft[u].A,n,-1);
}
}
int main(){
deg1 = read(); deg2 = read(); md = read();
for (int i = 0; i <= deg1; i++) F[i] = read();
for (int i = 0; i <= deg2; i++) G[i] = read();
conv(); CRT();
for (int i = 0; i <= deg; i++) printf("%lld ",ans[i]);
return 0;
}

任意模数NTT的更多相关文章

  1. BZOJ1042 HAOI2008硬币购物(任意模数NTT+多项式求逆+生成函数/容斥原理+动态规划)

    第一眼生成函数.四个等比数列形式的多项式相乘,可以化成四个分式.其中分母部分是固定的,可以多项式求逆预处理出来.而分子部分由于项数很少,询问时2^4算一下贡献就好了.这个思路比较直观.只是常数巨大,以 ...

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

    题目大意:给你两个多项式$f(x)$和$g(x)$以及一个模数$p(p\leqslant10^9)$,求$f*g\pmod p$ 题解:任意模数$NTT$,最大的数为$p^2\times\max\{n ...

  3. 【模板】任意模数NTT

    题目描述: luogu 题解: 用$fft$水过(什么$ntt$我不知道). 众所周知,$fft$精度低,$ntt$处理范围小. 所以就有了任意模数ntt神奇$fft$! 意思是这样的.比如我要算$F ...

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

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

  5. MTT:任意模数NTT

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

  6. 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)

    再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...

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

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

  8. 洛谷P4245 【模板】MTT(任意模数NTT)

    题目背景 模板题,无背景 题目描述 给定 22 个多项式 F(x), G(x)F(x),G(x) ,请求出 F(x) * G(x)F(x)∗G(x) . 系数对 pp 取模,且不保证 pp 可以分解成 ...

  9. Luogu 4245 【模板】任意模数NTT

    这个题还有一些其他的做法,以后再补,先记一下三模数$NTT$的方法. 发现这个题不取模最大的答案不会超过$10^5 \times 10^9 \times 10^9 = 10^{23}$,也就是说我们可 ...

随机推荐

  1. IntelliJ IDEA使用教程(非常全面)

    这个编辑器我就不再多做介绍了.直接开始新建maven hello world 的Java web项目啦 你电脑上得有jdk1.7,或者1.8,然后就是maven3.x吧,再有就是tomcat7以上吧. ...

  2. AngularJS:directive自定义的指令

    除了 AngularJS 内置的指令外,我们还可以创建自定义指令. 你可以使用 .directive 函数来添加自定义的指令. 要调用自定义指令,HTML 元素上需要添加自定义指令名. 使用驼峰法来命 ...

  3. 剑指offer(6)

    题目: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转 ...

  4. 莫烦sklearn学习自修第九天【过拟合问题处理】

    1. 过拟合问题可以通过调整机器学习的参数来完成,比如sklearn中通过调节gamma参数,将训练损失和测试损失降到最低 2. 代码实现(显示gamma参数对训练损失和测试损失的影响) from _ ...

  5. python数学第七天【期望的性质】

  6. Code::Blocks debug程序

    设置Settings--->Compiler, 打上勾: Produce debugging symbols [-g] 需要在settings->debugger settings-> ...

  7. nginx 卸载后重新安装/etc/nginx配置文件没了,cannot open /etc/nginx/nginx.conf (No such file or directory)

    sudo apt-get --purge remove nginx-common sudo apt-get --purge remove nginx* sudo apt-get autoremove ...

  8. flask 保存文件到 七牛云

    上篇文章队长讲述了如何把前端上传的文件保存到本地项目目录 本篇 讲述一下把前端上传的文件保存到 第三方存储(七牛云) 七牛云相关步骤思路: 首先 进去七牛云官网,注册并实名认证来获取一个七牛云账号和存 ...

  9. 洛谷 p1019 单词接龙

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

  10. react 入坑笔记(一)

    一些概念: 1.组件:概念等同于 vue 中的组件,字面意思,不过 vue 中组件是以 .vue 结尾,通过 vue-loader 编译成 js,而 react 组件就是 js. 2.jsx:js 语 ...