题目大意:给你两个多项式$f(x)$和$g(x)$以及一个模数$p(p\leqslant10^9)$,求$f*g\pmod p$

题解:任意模数$NTT$,最大的数为$p^2\times\max\{n,m\}\leqslant10^{23}$,所以一般选$3$个模数即可,求出这三个模数下的答案,然后中国剩余定理即可。

假设这一位的答案是$x$,三个模数分别为$A,B,C$,那么:

$$
x\equiv x_1\pmod{A}\\
x\equiv x_2\pmod{B}\\
x\equiv x_3\pmod{C}
$$

先把前两个合并:

$$
x_1+k_1A=x_2+k_2B\\
x_1+k_1A\equiv x_2\pmod{B}\\
k_1\equiv \frac{x_2-x_1}A\pmod{B}
$$

于是求出了$k_1$,也就求出了$x\equiv x_1+k_1A\pmod{AB}$,记$x_4=x_1+k_1A$

$$
x_4+k_4AB=x_3+k_3C\\
x_4+k_4AB\equiv x_3\pmod{C}\\
k_4\equiv \dfrac{x_3-x_4}{AB}\pmod{C}
$$

求出了$k_4$,$x\equiv x_4+k_4AB\pmod{ABC}$,因为$x<ABC$,所以$x=x_4+k_4AB$

卡点:$Wn$数组开小,中国剩余定理写错

C++ Code:

#include <algorithm>
#include <cstdio>
#include <cstring>
int mod;
namespace Math {
inline int pw(int base, int p, const int mod) {
static int res;
for (res = 1; p; p >>= 1, base = static_cast<long long> (base) * base % mod) if (p & 1) res = static_cast<long long> (res) * base % mod;
return res;
}
inline int inv(int x, const int mod) { return pw(x, mod - 2, mod); }
} const int mod1 = 998244353, mod2 = 1004535809, mod3 = 469762049, G = 3;
const long long mod_1_2 = static_cast<long long> (mod1) * mod2;
const int inv_1 = Math::inv(mod1, mod2), inv_2 = Math::inv(mod_1_2 % mod3, mod3);
struct Int {
int A, B, C;
explicit inline Int() { }
explicit inline Int(int __num) : A(__num), B(__num), C(__num) { }
explicit inline Int(int __A, int __B, int __C) : A(__A), B(__B), C(__C) { }
static inline Int reduce(const Int &x) {
return Int(x.A + (x.A >> 31 & mod1), x.B + (x.B >> 31 & mod2), x.C + (x.C >> 31 & mod3));
}
inline friend Int operator + (const Int &lhs, const Int &rhs) {
return reduce(Int(lhs.A + rhs.A - mod1, lhs.B + rhs.B - mod2, lhs.C + rhs.C - mod3));
}
inline friend Int operator - (const Int &lhs, const Int &rhs) {
return reduce(Int(lhs.A - rhs.A, lhs.B - rhs.B, lhs.C - rhs.C));
}
inline friend Int operator * (const Int &lhs, const Int &rhs) {
return Int(static_cast<long long> (lhs.A) * rhs.A % mod1, static_cast<long long> (lhs.B) * rhs.B % mod2, static_cast<long long> (lhs.C) * rhs.C % mod3);
}
inline int get() {
long long x = static_cast<long long> (B - A + mod2) % mod2 * inv_1 % mod2 * mod1 + A;
return (static_cast<long long> (C - x % mod3 + mod3) % mod3 * inv_2 % mod3 * (mod_1_2 % mod) % mod + x) % mod;
}
} ; #define maxn 131072 namespace Poly {
#define N (maxn << 1)
int lim, s, rev[N];
Int Wn[N | 1];
inline void init(int n) {
s = -1, lim = 1; while (lim < n) lim <<= 1, ++s;
for (register int i = 1; i < lim; ++i) rev[i] = rev[i >> 1] >> 1 | (i & 1) << s;
const Int t(Math::pw(G, (mod1 - 1) / lim, mod1), Math::pw(G, (mod2 - 1) / lim, mod2), Math::pw(G, (mod3 - 1) / lim, mod3));
*Wn = Int(1); for (register Int *i = Wn; i != Wn + lim; ++i) *(i + 1) = *i * t;
}
inline void NTT(Int *A, const int op = 1) {
for (register int i = 1; i < lim; ++i) if (i < rev[i]) std::swap(A[i], A[rev[i]]);
for (register int mid = 1; mid < lim; mid <<= 1) {
const int t = lim / mid >> 1;
for (register int i = 0; i < lim; i += mid << 1) {
for (register int j = 0; j < mid; ++j) {
const Int W = op ? Wn[t * j] : Wn[lim - t * j];
const Int X = A[i + j], Y = A[i + j + mid] * W;
A[i + j] = X + Y, A[i + j + mid] = X - Y;
}
}
}
if (!op) {
const Int ilim(Math::inv(lim, mod1), Math::inv(lim, mod2), Math::inv(lim, mod3));
for (register Int *i = A; i != A + lim; ++i) *i = (*i) * ilim;
}
}
#undef N
} int n, m;
Int A[maxn << 1], B[maxn << 1];
int main() {
scanf("%d%d%d", &n, &m, &mod); ++n, ++m;
for (int i = 0, x; i < n; ++i) scanf("%d", &x), A[i] = Int(x % mod);
for (int i = 0, x; i < m; ++i) scanf("%d", &x), B[i] = Int(x % mod);
Poly::init(n + m);
Poly::NTT(A), Poly::NTT(B);
for (int i = 0; i < Poly::lim; ++i) A[i] = A[i] * B[i];
Poly::NTT(A, 0);
for (int i = 0; i < n + m - 1; ++i) {
printf("%d", A[i].get());
putchar(i == n + m - 2 ? '\n' : ' ');
}
return 0;
}

  

[洛谷P4245]【模板】任意模数NTT的更多相关文章

  1. 洛谷 P4245 [模板]任意模数NTT —— 三模数NTT / 拆系数FFT(MTT)

    题目:https://www.luogu.org/problemnew/show/P4245 用三模数NTT做,需要注意时间和细节: 注意各种地方要取模!传入 upt() 里面的数一定要不超过2倍 m ...

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

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

  3. [题解] Luogu P4245 [模板]任意模数NTT

    三模NTT 不会... 都0202年了,还有人写三模NTT啊... 讲一个好写点的做法吧: 首先取一个阀值\(w\),然后把多项式的每个系数写成\(aw + c(c < w)\)的形式,换句话说 ...

  4. 洛谷.3803.[模板]多项式乘法(NTT)

    题目链接:洛谷.LOJ. 为什么和那些差那么多啊.. 在这里记一下原根 Definition 阶 若\(a,p\)互质,且\(p>1\),我们称使\(a^n\equiv 1\ (mod\ p)\ ...

  5. 洛谷.4721.[模板]分治FFT(NTT)

    题目链接 换一下形式:\[f_i=\sum_{j=0}^{i-1}f_jg_{i-j}\] 然后就是分治FFT模板了\[f_{i,i\in[mid+1,r]}=\sum_{j=l}^{mid}f_jg ...

  6. 洛谷.4512.[模板]多项式除法(NTT)

    题目链接 多项式除法 & 取模 很神奇,记录一下. 只是主要部分,更详细的和其它内容看这吧. 给定一个\(n\)次多项式\(A(x)\)和\(m\)次多项式\(D(x)\),求\(deg(Q) ...

  7. 【模板】任意模数NTT

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

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

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

  9. MTT:任意模数NTT

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

随机推荐

  1. 重装系统之无法在驱动器0的分区1上安装windows

    在通过U盘或光盘安装win8/win8.1/win10 时,遇到无法安装的问题,提示“无法在驱动器0的分区1上安装windows”,格式化分区也不能解决,进而提示Windows无法安装到这个磁盘,选中 ...

  2. Luogu P2312 解方程

    据大佬的说法这种大力乱搞题出在除NOIp以外的任何比赛都是很好的然而就是被出在了NOIp 首先对于想直接上高精的同学,我还是祝你好运吧. 我们考虑一个十分显然的性质,若\(a=b\),则对于任一自然数 ...

  3. AtCoder ExaWizards 2019 简要题解

    AtCoder ExaWizards 2019 简要题解 Tags:题解 link:https://atcoder.jp/contests/exawizards2019 很水的一场ARC啊,随随便便就 ...

  4. linux awk 内置函数实例

    awk内置函数,主要分4种:算数函数.字符串函数.时间函数.一般函数 一.算术函数 以下算术函数执行与 C 语言中名称相同的子例程相同的操作: 函数名 说明 atan2( y, x ) 返回 y/x ...

  5. 2018年高教社杯全国大学生数学建模竞赛B题解题思路

    题目 先贴下B题的题目吧 问题B    智能RGV的动态调度策略 图1是一个智能加工系统的示意图,由8台计算机数控机床(Computer Number Controller,CNC).1辆轨道式自动引 ...

  6. 手动编写的几个简单的puppet管理配置

    puppet在自动化配置管理方面有很强大的优势,这里就不做过多介绍了,下面记录下几个简单的puppet管理配置: 一.首先在服务端和客户端安装puppet和facter 1)服务端 安装Puppet ...

  7. http状态码 301、302区别

    http状态码301和302详解及区别——辛酸的探索之路 [HTTP]状态码301与302 HTTP返回码中301与302的区别 http状态码301和302详解及区别

  8. Visual Studio 2015的安装及单元测试练习

    第一部分:Visual Studio 2015的安装 我电脑系统是win10,所以安装的是Visual Studio 2015,安装步骤部分截图如图所示: 1.安装类型选项界面:可以选择默认安装,可以 ...

  9. 《Linux内核设计》第17章学习笔记

  10. 异常 try – finally 注意的地方

    finally 异常机制中还有一个重要的部分,就是finally, catch后面可以跟finally语句,语法如下所示:   try{ //可能抛出异常 }catch(Exception e){ / ...