P4245 MTT

题意

传送门 P4245 【模板】任意模数多项式乘法

题解

对于 p = 1 0 9 p=10^9 p=109 范围的模数以及最高次在 n , m = 1 0 5 n,m=10^5 n,m=105 范围的多项式,结果多项式的每一项系数上界为 p 2 ⋅ ( n + m ) p^2\cdot (n + m) p2⋅(n+m),使用三模数NTT 求解,最后根据中国剩余定理合并即可。考虑到数据范围,需要使用 __int128。总时间复杂度 O ( ( n + m ) log ⁡ ( n + m ) ) O\big((n+m)\log (n+m)\big) O((n+m)log(n+m))。

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
namespace MTT {
using ll = long long;
constexpr int N = 3;
constexpr ll MOD[N] = {998244353, 1004535809, 469762049}, G = 3;
ll power(ll x, ll n, ll mod) {
    ll res = 1;
    x %= mod;
    while (n > 0) {
        if (n & 1) {
            res = res * x % mod;
        }
        x = x * x % mod, n >>= 1;
    }
    return res;
}

vector<int> rev;
ll _mod;
struct Poly : vector<ll> {
    Poly() {}
    Poly(int n) : vector<ll>(n) {}
    Poly(const vector<ll> &a) : vector<ll>(a) {}
    Poly(const initializer_list<ll> &list) : vector<ll>(list) {}
    void fft(int n, bool inverse) {
        if ((int)rev.size() != n) {
            rev.resize(n);
            for (int i = 0; i < n; ++i)
                rev[i] = rev[i >> 1] >> 1 | (i & 1 ? n >> 1 : 0);
        }
        resize(n);
        for (int i = 0; i < n; ++i)
            if (i < rev[i])
                std::swap(at(i), at(rev[i]));
        ll mod = _mod;
        for (int m = 1; m < n; m <<= 1) {
            int m2 = m << 1;
            ll _w = power(inverse ? power(G, mod - 2, mod) : G, (mod - 1) / m2, mod);
            for (int i = 0; i < n; i += m2)
                for (int w = 1, j = 0; j < m; ++j, w = w * _w % mod) {
                    ll &x = at(i + j), &y = at(i + j + m), t = w * y % mod;
                    y = x - t;
                    if (y < 0)
                        y += mod;
                    x += t;
                    if (x >= mod)
                        x -= mod;
                }
        }
    }
    void dft(int n) { fft(n, 0); };
    void idft(int n) {
        fft(n, 1);
        ll mod = _mod;
        for (int i = 0, inv = power(n, mod - 2, mod); i < n; ++i)
            at(i) = at(i) * inv % mod;
    }
    Poly operator*(const Poly &p) const {
        auto a = *this, b = p;
        int k = 1, n = a.size() + b.size() - 1;
        while (k < n)
            k <<= 1;
        a.dft(k), b.dft(k);
        ll mod = _mod;
        for (int i = 0; i < k; ++i)
            a[i] = a[i] * b[i] % mod;
        a.idft(k);
        a.resize(n);
        return a;
    }
};

vector<ll> mul(vector<ll> &a, vector<ll> &b, ll p) {
    int n = a.size(), m = b.size();
    vector<Poly> tmp(N);
    for (int i = 0; i < N; ++i) {
        _mod = MOD[i];
        Poly f(a), g(b);
        tmp[i] = f * g;
    }
    using lll = __int128;
    vector<lll> c(n + m - 1);
    lll _p = 1;
    for (int i = 0; i < N; ++i) {
        _p *= MOD[i];
    }
    for (int i = 0; i < N; ++i) {
        ll x = 1;
        for (int j = 0; j < N; ++j) {
            if (i != j) {
                x *= MOD[j];
            }
        }
        ll y = power(x, MOD[i] - 2, MOD[i]);
        for (int j = 0; j < n + m - 1; ++j) {
            c[j] += (lll)tmp[i][j] * x * y;
        }
    }
    vector<ll> res(n + m - 1);
    for (int i = 0; i < n + m - 1; ++i) {
        res[i] = c[i] % _p % p;
    }
    return res;
}
}  // namespace MTT
using ll = long long;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m, p;
    cin >> n >> m >> p;
    n += 1;
    m += 1;
    vector<ll> f(n);
    vector<ll> g(m);
    for (int i = 0; i < n; ++i) {
        cin >> f[i];
    }
    for (int i = 0; i < m; ++i) {
        cin >> g[i];
    }
    auto res = MTT::mul(f, g, p);
    for (int i = 0; i < n + m - 1; ++i) {
        cout << res[i] << " \n"[i + 1 == n + m - 1];
    }

    return 0;
}
相关推荐
码之气三段.14 小时前
牛客周赛 Round 145-E(写了200行的史山)
算法·深度优先
Hwang25214 小时前
Attention-04-decoder部分
算法
计算机安禾14 小时前
【算法分析与设计】第13篇:最小生成树:Prim算法与Kruskal算法的比较研究
大数据·人工智能·算法
vortex515 小时前
国密(商用密码)算法核心参数速查
算法·密码学
wuweijianlove15 小时前
算法中的记忆化思想与重复子问题优化的技术5
算法
小江的记录本16 小时前
【JVM虚拟机】垃圾回收GC:垃圾判定算法:引用计数法、可达性分析算法(附《思维导图》+《面试高频考点清单》)
java·jvm·后端·python·算法·spring·面试
Hello.Reader16 小时前
算法基础(十四)—— 随机化快速排序为什么平均表现很好
算法
吴可可12316 小时前
Teigha中OdGe几何库详解及C#使用
算法
爱喝水的鱼丶17 小时前
SAP-ABAP:变量、常量、结构与内表声明(10篇博客合集) 第六篇:ABAP 7.40+新特性:声明语法的简化写法与兼容注意事项
运维·服务器·开发语言·学习·算法·sap·abap
国科安芯17 小时前
AS32S601商业航天级抗辐照MCU芯片:架构设计与技术特性研究
单片机·嵌入式硬件·算法·安全·架构·risc-v