// author: ycp | https://ycpedef.github.io
// #pragma GCC diagnostic error "-std=c++11"
// #pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdarg>
#include <cmath>
#define debug(x) cerr << #x << " = " << x << endl
#define debugf(...) fprintf(stderr, __VA_ARGS__)
#define wlog(fmt, ...) fprintf(stderr, "<%s:%d> " fmt "\n", __func__, __LINE__, ## __VA_ARGS__)
using namespace std;
template<class T> bool cmax(T &a, T b) { return b > a ? (a = b, 1) : 0; }
template<class T> bool cmin(T &a, T b) { return b < a ? (a = b, 1) : 0; }
template<class T> void read(T &a) {
a = 0; char c = getchar(); int f = 0;
while (!isdigit(c)) { f ^= c == '-', c = getchar(); }
while (isdigit(c)) { a = a * 10 + (c ^ 48), c = getchar(); }
a *= f ? -1 : 1;
}
struct Fastin {
template<class T> Fastin& operator >> (T &x) { read(x); return *this; }
} fastin;
#include <utility>
#include <cstring>
#include <cstdio>
#include <cctype>
namespace poly {
using u64 = unsigned long long;
using std::forward;
const u64 mod = 998244353;
const u64 G = 3;
int *log2 = nullptr, *rev = nullptr, rev_limit = 1;
u64 **w;
inline u64 power(u64 a, int b);
inline void swap(u64 &a, u64 &b);
inline void reverse(u64* p1, u64* p2);
inline void read(u64 &a);
inline void init(int n);
struct poly_t {
u64 *src; int deg;
inline void read(int);
inline void print(int) const;
poly_t(int); poly_t(int, int);
poly_t(const poly_t &); poly_t(poly_t &&);
~poly_t() { delete[] src; }
void resize(int);
void copy(const poly_t &);
poly_t& operator = (const poly_t &);
poly_t& operator = (poly_t &&);
u64& operator [] (const int &x) { return src[x]; }
u64 operator [] (const int &x) const { return src[x]; }
inline void NTT(int);
inline void DFT() { return NTT(1); }
inline void IDFT() { return NTT(-1); }
};
// -------------------------- poly_t start ----------------------------
#define cp(dest, src, cnt) memcpy(dest, src, cnt * sizeof(u64))
inline void poly_t::copy(const poly_t &p) {
deg = p.deg, src = new u64[deg](); cp(src, p.src, deg);
}
void poly_t::resize(int c) {
if (c <= deg) return;
u64 *pre = src; src = new u64[c](); cp(src, pre, deg);
deg = c, delete[] pre;
}
#undef cp
poly_t::poly_t(int siz) { wlog("new");deg = siz; src = new u64[deg](); }
poly_t::poly_t(int siz, int n) { wlog("new");deg = siz; src = new u64[deg](); read(n); }
poly_t::poly_t(const poly_t& p) { wlog("copy");copy(p); }
poly_t::poly_t(poly_t &&p) { wlog("move");deg = p.deg, src = p.src, p.src = nullptr; }
poly_t& poly_t::operator = (const poly_t& p) { wlog("copy");
if (this != &p) { delete[] src; copy(p); }
return *this;
}
poly_t& poly_t::operator = (poly_t &&p) { wlog("move");
if (this != &p) {
delete[] src; deg = p.deg, src = p.src, p.src = nullptr;
}
return *this;
}
inline void poly_t::read(int n) {
for (int i = 0; i < n; i++) { poly::read(src[i]); }
}
inline void poly_t::print(int n) const {
for (int i = 0; i < n; i++) { printf("%llu ", src[i]); } putchar('\n');
}
inline void poly_t::NTT(int mode) {
for (int i = 0; i < deg; i++) {
if (i < rev[i]) poly::swap(src[i], src[rev[i]]);
}
u64 *f = src, *g, t1, t2;
for (int k = 1, i, j, l, x = 1; (k << 1) <= deg; k <<= 1, x++) {
l = k << 1;
for (i = 0; i < deg; i += l) {
for (j = i, g = w[x]; j < i + k; j++, g++) {
t1 = f[j], t2 = (((*g) * f[j | k])) % mod;
f[j] = t1 + t2;
f[j | k] = t1 - t2 + mod;
}
}
if (k & (1 << 16)) {
for (int i = 0; i < deg; i++) {
f[i] %= mod;
}
}
}
if (mode < 0) {
poly::reverse(f + 1, f + deg);
u64 inv = power(deg, mod - 2);
for (int i = 0; i < deg; i++) f[i] *= inv;
}
for (int i = 0; i < deg; i++) f[i] %= mod;
}
template<typename T>
poly_t inv(T &&p) {
poly_t f(forward<T>(p));
return f;
}
template<typename T>
poly_t ln(T &&p) {
poly_t f(forward<T>(p));
return f;
}
template<typename T>
poly_t exp(T &&p) {
poly_t f(forward<T>(p));
return f;
}
template<typename T1, typename T2>
poly_t operator * (T1 &&p1, T2 &&p2) {
poly_t a(forward<T1>(p1)), b(forward<T2>(p2));
//wlog("DFT");
a.DFT(), b.DFT();
poly_t c(a.deg);
for (int i = 0; i < c.deg; i++) (c[i] = a[i] * b[i]) %= mod;
//wlog("IDFT");
c.IDFT();
//wlog("complete");
return c;
}
//------------------------- poly_t end -------------------------------
inline u64 power(u64 a, int b) {
u64 res = 1;
//debugf("power(%llu, %d) ", a, b);
while (b) { if (b & 1) (res *= a) %= mod; b >>= 1, (a *= a) %= mod; }
//debugf("= %llu\n", res);
return res;
}
inline void swap(u64 &a, u64 &b) { u64 t = a; a = b, b = t; }
inline void reverse(u64* p1, u64* p2) { p2--; while (p1 < p2) { swap(*p1, *p2), p1++, p2--; } }
inline void read(u64 &a) {
a = 0; char c = getchar(); int f = 0;
while (!isdigit(c)) { f ^= c == '-', c = getchar(); }
while (isdigit(c)) { a = a * 10 + (c ^ 48), c = getchar(); }
a *= f ? -1 : 1;
}
inline void init(int n = 1e6) {
//delete[] poly::log2, poly::log2 = new int[n + 10]();
//poly::log2[0] = -1;
//for (int i = 1; i <= n; i++) {
// poly::log2[i] = poly::log2[i >> 1] + 1;
//}
delete[] rev, rev = new int[n + 10]();
int log_limit = 1;
while ((rev_limit << 1) <= n) rev_limit <<= 1, log_limit++;
//debug(rev_limit);
for (int i = 0; i < rev_limit; i++) {
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) * (n >> 1));
}
w = new u64*[log_limit + 10]();
for (int i = 0; i < log_limit; i++) w[i] = new u64[1 << i]();
for (int i = 0, l; i < log_limit; i++) {
l = (1 << i);
u64 g0 = power(G, (mod - 1) / l), *p = w[i];
*p = 1;
//debug(g0);
for (int j = 1; j < l; j++, p++) { *(p + 1) = *p * g0 % mod; }
//for (int j = 0; j < l; j++) {
// debugf("w[%d][%d] = %llu\n", i, j, w[i][j]);
//}
}
}
} // namespace poly
using poly::poly_t;
int n, m;
struct io_t {
#define gc() (s == t && (t = (s = in) + fread(in, 1, SIZ, stdin), s == t) ? EOF : *s++)
static const int SIZ = 1 << 25;
char in[SIZ], *s = in, *t = in;
template<typename T>
io_t& operator>>(T& x) {
x = 0;
char c = gc();
while (c < '0') c = gc();
while (c >= '0') x = x * 10 + c - 48, c = gc();
return *this;
}
} io;
int main() {
//freopen("poly.in", "r", stdin);
//freopen("poly.out", "w", stdout);
io >> n >> m;
int len = 1 << (unsigned)(std::ceil(log2(n + m + 1)));
poly::init(len);
poly_t a(len);
for (int i = 0; i <= n; i++) io >> a[i];
poly_t b(len);
for (int i = 0; i <= m; i++) io >> b[i];
(std::move(a) * std::move(b)).print(n + m + 1);
return 0;
}
Compilation | N/A | N/A | Compile OK | Score: N/A | 显示更多 |
Subtask #1 Testcase #1 | 41.13 us | 44 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #2 | 52.692 ms | 12 MB + 860 KB | Accepted | Score: 100 | 显示更多 |
Subtask #1 Testcase #3 | 24.29 ms | 6 MB + 8 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #4 | 24.456 ms | 5 MB + 1020 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #5 | 41.75 us | 44 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #6 | 40.36 us | 44 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #7 | 41.28 us | 44 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #8 | 47.346 ms | 12 MB + 528 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #9 | 47.357 ms | 12 MB + 528 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #10 | 42.233 ms | 12 MB + 192 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #11 | 52.594 ms | 12 MB + 940 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #12 | 53.508 ms | 11 MB + 820 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #13 | 39.34 us | 44 KB | Accepted | Score: 0 | 显示更多 |