#include <iostream>
using i64 = long long;
namespace poly {
const i64 MOD = 998244353, g = 3;
const int MaxBit = 22, MaxLen = 1 << MaxBit;
const int N = MaxLen | 7;
typedef i64 polyT[N];
i64 pow(i64 a, i64 k);
int rev[N];
i64 w[N];
struct poly_ {
poly_() {
for (int i = 1; i < MaxLen; ++i)
rev[i] = rev[i >> 1] >> 1 | (i & 1 ? MaxLen >> 1 : 0);
w[MaxLen >> 1] = 1;
i64 x = pow(g, (MOD - 1) / MaxLen);
for (int i = (MaxLen >> 1) + 1; i < MaxLen; ++i) w[i] = w[i - 1] * x % MOD;
for (int i = (MaxLen >> 1) - 1; ~i; --i) w[i] = w[i << 1];
}
} p_;
void ntt(i64 a[], int n, int on);
void mul(i64 a[], int n, i64 b[], int m, i64 c[]);
void ntt(i64 a[], int n, int on) {
static i64 f[N], x;
int s = 0; while (n << s < MaxLen) ++s;
for (int i = 0; i < n; ++i) f[rev[i] >> s] = a[i];
for (int l = 1; l < n; l <<= 1)
for (int i = 0; i < n; i += l << 1)
for (int j = 0; j < l; ++j)
x = (f[i | j | l] %= MOD) * w[j | l] % MOD,
f[i | j | l] = f[i | j] - x, f[i | j] += x;
if (on == 1)
for (int i = 0; i < n; ++i) a[i] = f[i] % MOD;
else {
a[0] = f[0] % MOD * (x = pow(n, MOD - 2)) % MOD;
for (int i = 1; i < n; ++i) a[i] = f[n - i] % MOD * x % MOD;
}
}
void mul(i64 a[], int n, i64 b[], int m, i64 c[]) {
for (n = m = n + m - 1; n ^ (n & -n); n += n & -n);
ntt(a, n, 1), ntt(b, n, 1);
for (int i = 0; i < n; ++i) c[i] = a[i] * b[i] % MOD;
ntt(c, n, -1);
}
i64 pow(i64 a, i64 k) {
i64 t = 1;
for (; k; a = a * a % MOD, k >>= 1) if (k & 1) t = t * a % MOD;
return t;
}
};
using poly::MOD;
int main() {
static int n, m;
static poly::polyT a, b, c;
scanf("%d%d", &n, &m), ++n, ++m;
for (int i = 0; i < n; ++i) scanf("%lld", a + i);
for (int i = 0; i < m; ++i) scanf("%lld", b + i);
poly::mul(a, n, b, m, c);
for (int i = 0; i < n + m - 1; ++i) printf("%lld ", (c[i] + MOD) % MOD);
return 0;
}
namespace poly
猜你喜欢
转载自www.cnblogs.com/Ryedii-blog/p/12490175.html
今日推荐
周排行