From c1d49f8976b3101530514d96732f6cf9c2689f9f Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Fri, 2 Dec 2022 22:54:50 +0800 Subject: [PATCH] =?UTF-8?q?P4512=20=E3=80=90=E6=A8=A1=E6=9D=BF=E3=80=91?= =?UTF-8?q?=E5=A4=9A=E9=A1=B9=E5=BC=8F=E9=99=A4=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://www.luogu.com.cn/record/96343801 --- Luogu/P4512/P4512.cpp | 194 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 Luogu/P4512/P4512.cpp diff --git a/Luogu/P4512/P4512.cpp b/Luogu/P4512/P4512.cpp new file mode 100644 index 00000000..2db4e102 --- /dev/null +++ b/Luogu/P4512/P4512.cpp @@ -0,0 +1,194 @@ +#include +#include +#include + +using std::cin; +using std::cout; +const char endl = '\n'; + +const int mod = 998244353; + +constexpr long long binpow(long long a, long long b) { + a %= mod; + + long long res = 1; + + while (b) { + if (b & 1) res = res * a % mod; + a = a * a % mod; + b >>= 1; + } + + return res; +} + +class Poly : public std::vector { + private: + static void number_theoretic_transform(std::vector &a) { + if (a.size() == 1) return; + + // assert(a.size() == (1 << std::__lg(a.size()))); + int k = std::__lg(a.size()); + + for (int i = 0; i < a.size(); i++) { + int t = 0; + + for (int j = 0; j < k; j++) { + if (i & (1 << j)) { + t |= 1 << (k - j - 1); + } + } + + if (i < t) std::swap(a[i], a[t]); + } + + for (int len = 2; len <= a.size(); len <<= 1) { + int m = len >> 1; + long long wn = binpow(3, (mod - 1) / len); + + for (int i = 0; i < a.size(); i += len) { + long long w = 1; + + for (int j = 0; j < m; j++) { + long long u = a[i + j], + v = a[i + j + m] * w % mod; + + a[i + j] = ((u + v) % mod + mod) % mod; + a[i + j + m] = ((u - v) % mod + mod) % mod; + w = w * wn % mod; + } + } + } + } + + static void dft(std::vector &a) { + number_theoretic_transform(a); + } + + static void idft(std::vector &a) { + number_theoretic_transform(a); + std::reverse(a.begin() + 1, a.end()); + long long inv = binpow(a.size(), mod - 2); + std::transform(a.begin(), a.end(), a.begin(), [&](long long x) { + return x * inv % mod; + }); + } + + public: + using std::vector::vector; + + Poly() = default; + + Poly(const std::vector &__v) + : std::vector(__v) {} + + Poly(std::vector &&__v) + : std::vector(std::move(__v)) {} + + Poly operator*(const Poly &b) { + int n = size() - 1, + m = b.size() - 1, + k = 1 << (std::__lg(n + m) + 1), + inv = binpow(k, mod - 2); + + std::vector f(*this), g(b); + + f.resize(k); + dft(f); + g.resize(k); + dft(g); + + for (int i = 0; i < k; i++) { + f[i] = f[i] * g[i] % mod; + } + + idft(f); + f.resize(n + m + 1); + + return Poly(f); + } + + Poly operator/(const Poly &b) { + Poly c{inv(b)}; + + return *this * c; + } + + static Poly inv(Poly a) { + if (a.size() == 1) return Poly{binpow(a[0], mod - 2)}; + + int n = a.size(), + k = 1 << (std::__lg(n << 1) + 1); + Poly b{a}; + + a.resize(k); + dft(a); + + b.resize(n + 1 >> 1); + b = inv(b); + b.resize(k); + dft(b); + + for (int i = 0; i < k; i++) { + b[i] = (2 - a[i] * b[i] % mod + mod) % mod * b[i] % mod; + } + + idft(b); + b.resize(n); + + return b; + } +} poly; + +int main() { + std::ios::sync_with_stdio(false); + cin.tie(nullptr); + + int n, m; + + cin >> n >> m; + + Poly f(n + 1), g(m + 1); + + for (int i = 0; i <= n; i++) { + cin >> f[i]; + } + + for (int i = 0; i <= m; i++) { + cin >> g[i]; + } + + Poly rev_f{f}, rev_g{g}; + + std::reverse(rev_f.begin(), rev_f.end()); + std::reverse(rev_g.begin(), rev_g.end()); + rev_g.resize(n - m + 1); + rev_g = Poly::inv(rev_g); + rev_f = rev_g * rev_f; + + Poly q(n - m + 1), r(m); + + for (int i = 0; i <= n - m; i++) { + q[i] = rev_f[n - m - i]; + } + + g = g * q; + + for (int i = 0; i < m; i++) { + r[i] = ((f[i] - g[i]) % mod + mod) % mod; + } + + for (int i = 0; i <= n - m; i++) { + cout << q[i] << ' '; + } + + cout << endl; + + for (int i = 0; i < m; i++) { + cout << r[i] << ' '; + } + + cout << endl; + + return 0; +}