Description

给定 \(2\) 个多项式 \(F(x), G(x)\),请求出 \(F(x) * G(x)\)。

系数对 \(p\) 取模,且不保证 \(p\) 可以分解成 \(p = a \cdot 2^k + 1\) 之形式。

Solution

设 \(m_1=469762049,m_2=998244353,m_3=1004535809​\),有

\[\begin{cases}
x\equiv c_1\pmod{m_1}\\
x\equiv c_2\pmod{m_2}\\
x\equiv c_3\pmod{m_3}
\end{cases}
\]

用中国剩余定理合并前两个同余式,得到

\[\begin{cases}
x\equiv c_3\pmod{m_3}\\
x\equiv c_4\pmod{m_1m_2}
\end{cases}
\]

设 \(x=km_1m_2+c_4\),有

\[km_1m_2+c_4\equiv c_3\pmod{m_3}\\
k\equiv (c_3-c_4)m_1^{-1}m_2^{-1}\pmod{m_3}
\]

设 \(k=am_3+(c_3-c_4)m_1^{-1}m_2^{-1}​\),有

\[x=(am_3+(c_3-c_4)m_1^{-1}m_2^{-1})m_1m_2+c_4\\
x\equiv (c_3-c_4)m_1^{-1}m_2^{-1}m_1m_2+c_4\pmod{m_1m_2m_3}
\]

其中 \(m_1^{-1}m_2^{-1}\) 是在模 \(m_3\) 意义下的。

注意 \(exgcd\) 的返回值可能是负数,要处理一下;在 \(ksm(a, b, p)\) 之前先将 \(a\) 对 \(p\) 取模。

Code

#include <cstdio>
#include <algorithm> typedef long long LL; const int N = 262150;
int a[N], b[N], n, m, nn, mm, pp, R[N], L, p[N], g[N]; LL f[2][N]; int read() {
int x = 0; char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
return x;
}
void exgcd(LL a, LL b, LL &x, LL &y) {
if (!b) { x = 1, y = 0; return; }
exgcd(b, a % b, y, x), y -= a / b * x;
}
LL ksm(LL a, LL b, LL p) {
LL res = 1;
for (; b; b >>= 1, a = 1LL * a * a % p)
if (b & 1) res = 1LL * res * a % p;
return res;
}
LL mul(LL a, LL b, LL p) {
LL res = 0; int f = 1;
if (a < 0) a = -a, f = -f; if (a >= p) a %= p;
if (b < 0) b = -b, f = -f; if (b >= p) b %= p;
for (; b; b >>= 1, a += a + a < p ? a : a - p)
if ((b & 1) && (res += a) >= p) res -= p;
return res * f;
}
void NTT(LL *A, int f, int t) {
for (int i = 0; i < n; ++i) if (i < R[i]) std::swap(A[i], A[R[i]]);
for (int i = 1; i < n; i <<= 1) {
int wn = ksm(f ? 3 : g[t], (p[t] - 1) / (i << 1), p[t]);
for (int j = 0, r = i << 1; j < n; j += r) {
int w = 1;
for (int k = 0; k < i; ++k, w = 1LL * w * wn % p[t]) {
int x = A[j + k], y = 1LL * w * A[i + j + k] % p[t];
A[j + k] = (x + y) % p[t], A[i + j + k] = (x - y + p[t]) % p[t];
}
}
}
}
void solve(int t, int k) {
LL c[N] = {}, d[N] = {};
for (int i = 0; i <= nn; ++i) c[i] = a[i];
for (int i = 0; i <= mm; ++i) d[i] = b[i];
NTT(c, 1, t), NTT(d, 1, t);
for (int i = 0; i < n; ++i) f[k][i] = 1LL * c[i] * d[i] % p[t];
NTT(f[k], 0, t);
int inv = ksm(n, p[t] - 2, p[t]);
for (int i = 0; i <= m; ++i) f[k][i] = 1LL * f[k][i] * inv % p[t];
}
int main() {
nn = read(), mm = read(), pp = read();
for (int i = 0; i <= nn; ++i) a[i] = read();
for (int i = 0; i <= mm; ++i) b[i] = read();
m = nn + mm; for (n = 1; n <= m; n <<= 1) ++L;
for (int i = 0; i < n; ++i) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));
p[1] = 469762049, p[2] = 998244353, p[3] = 1004535809;
g[1] = 156587350, g[2] = 332748118, g[3] = 334845270;
solve(1, 0), solve(2, 1);
LL mod = 1LL * p[1] * p[2], x, y;
exgcd(p[1], p[2], x, y), x = (x % mod + mod) % mod;
for (int i = 0; i <= m; ++i) f[0][i] = (f[0][i] + mul(mul(x, f[1][i] - f[0][i] + mod, mod), p[1], mod)) % mod;
solve(3, 1);
LL inv = ksm(mod % p[3], p[3] - 2, p[3]);
for (int i = 0; i <= m; ++i) printf("%lld ", (mul(((f[1][i] - f[0][i]) % p[3] + p[3]) * inv % p[3], mod, pp) + f[0][i]) % pp);
return 0;
}

[Luogu 4245] 任意模数NTT的更多相关文章

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

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

  2. 【模板】任意模数NTT

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

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

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

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

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

  5. 任意模数NTT

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

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

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

  7. MTT:任意模数NTT

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

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

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

  9. 洛谷 4245 【模板】任意模数NTT——三模数NTT / 拆系数FFT

    题目:https://www.luogu.org/problemnew/show/P4245 三模数NTT: 大概是用3个模数分别做一遍,用中国剩余定理合并. 前两个合并起来变成一个 long lon ...

随机推荐

  1. [JavaScript] 函数节流(throttle)和函数防抖(debounce)

    js 的函数节流(throttle)和函数防抖(debounce)概述 函数防抖(debounce) 一个事件频繁触发,但是我们不想让他触发的这么频繁,于是我们就设置一个定时器让这个事件在 xxx 秒 ...

  2. mac 卸载通过官网下载包安装的node

    sudo rm -rf /usr/local/{bin/{node,npm},lib/node_modules/npm,lib/node,share/man/*/node.*}

  3. Dynamics 365中极特殊语言的文字搜索结果异常

    微软动态CRM专家罗勇 ,回复316或者20190314可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . 有些比较少见的问题, ...

  4. iOS---------获取当前年份

    NSDate *  senddate=[NSDate date]; NSDateFormatter  *dateformatter=[[NSDateFormatter alloc] init]; [d ...

  5. UI第三方

    自定义下拉刷新控件 - RefreshableView(支持所有控件的下拉刷新)https://blog.csdn.net/cjh_android/article/details/52462367 亲 ...

  6. go语言框架gin之集成swagger

    1.安装swag 在goLand中直接使用go get -u github.com/swaggo/swag/cmd/swag命令安装会报错 翻了很多博客,都没找到太合适的办法,根据博客中所写的操作还是 ...

  7. C#标识符与关键字

    标识符是指在程序中用来表示实物的单词,是分配给类型(类.结构.枚举.接口或委托).成员.变量或命名空间的名称.有效标识符必须遵循以下原则: 标识符不能以数字开头也不能包含空格: 标识符可以包含大小写字 ...

  8. SHA1withRSA加签名和验签名

    利用私钥加签名: //contentForSign为需加标签的字符串 public String signWhithsha1withrsa(string contentForSign) { strin ...

  9. WPF软件开发系统之二——水环境检测Surface触摸屏软件开发

    该系统采用C#.WPF语言开发,开发工具Visual Studio 2015.Blend,环境WIN7系统及以上,适用于PC.Windows触摸屏Surface等设备. 部分截图效果如下: 开发工具环 ...

  10. Windows苹果安卓手机远程桌面客户端推荐

    适用于:Windows 10.Windows 8.1.Windows Server 2012 R2.Windows Server 2016 最近公司电脑从Windows7升级到了Windows10,然 ...