Problem:
Score : 100 points

Problem Statement

You are given two integer arrays a_0, a_1, ..., a_{N - 1} and b_0, b_1, ..., b_{M - 1}. Calculate the array c_0, c_1, ..., c_{(N - 1) + (M - 1)}, defined by c_i = \sum_{j = 0}^i a_j b_{i - j} \bmod 998244353.

Constraints

1 \leq N, M \leq 524288

0 \leq a_i, b_i < 998244353

All values in Input are integer.

Input

Input is given from Standard Input in the following format:

N M
a_0 a_1 ... a_{N-1}
b_0 b_1 ... b_{M-1}

Output

Print the answer in the following format:

c_0 c_1 ... c_{(N - 1) + (M - 1)}

Sample Input 1

4 5
1 2 3 4
5 6 7 8 9

Sample Output 1

5 16 34 60 70 70 59 36

Sample Input 2

1 1
10000000
10000000

Sample Output 2

871938225

Solution in C (GCC 9.2.1) (judge verdict: Accepted)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>

//fast(?) Input
#define buf_sz 1<<24
char buf[buf_sz];
unsigned int nextint(){
	static int id = 0;
	if(id == 0)read(0, buf, buf_sz);
	unsigned int res = 0;
	while(id<buf_sz && buf[id]<'0' || '9'<buf[id])id++;
	while(id<buf_sz && '0'<=buf[id] && buf[id]<='9'){
		res *= 10;
		res += buf[id++] - '0';
	}if(id>=buf_sz)exit(1);
	return res;
}

long modpow(long x, long y, long m){
	long res = 1;
	while(y){
		if(y&1)res = res * x % m;
		x = x * x % m;
		y >>= 1;
	}
	return res;
}

const long mod = 998244353;
const long pr = 3;

void butterfly(long a[], int h){
	static bool first = true;
	static long sum_e[30];
	if(first){
		first = false;
		long es[30], ies[30];
		int cnt2 = __builtin_ctz(mod - 1);
		long e = modpow(pr, (mod-1)>>cnt2, mod);
		long ie = modpow(e, mod-2, mod);
		for(int i=cnt2; i>=2; i--){
			es[i-2] = e;
			ies[i-2] = ie;
			e = e * e % mod;
			ie = ie * ie % mod;
		}
		long now = 1;
		for(int i=0; i<=cnt2-2; i++){
			sum_e[i] = es[i] * now % mod;
			now = now * ies[i] % mod;
		}
	}
	for(int ph=1; ph<=h; ph++){
		int w = 1<<(ph-1), p=1<<(h-ph);
		long now = 1;
		for(int s=0; s<w; s++){
			int offset = s<<(h-ph+1);
			for(int i=0; i<p; i++){
				long l = a[i+offset],
					 r = a[i+offset+p] * now % mod;
				a[i+offset] = (l + r) % mod;
				a[i+offset+p] = (l - r + mod) % mod;
			}
			now = now * sum_e[__builtin_ctz(~s)] % mod;
		}
	}
}
void butterfly_inv(long a[], int h){
	static bool first = true;
	static long sum_ie[30];
	if(first){
		first = false;
		long es[30], ies[30];
		int cnt2 = __builtin_ctz(mod - 1);
		long e = modpow(pr, (mod-1)>>cnt2, mod);
		long ie = modpow(e, mod-2, mod);
		for(int i=cnt2; i>=2; i--){
			es[i-2] = e;
			ies[i-2] = ie;
			e = e * e % mod;
			ie = ie * ie % mod;
		}
		long now = 1;
		for(int i=0; i<=cnt2-2; i++){
			sum_ie[i] = ies[i] * now % mod;
			now = now * es[i] % mod;
		}
	}
	for(int ph=h; ph>=1; ph--){
		int w = 1<<(ph-1), p=1<<(h-ph);
		long inow = 1;
		for(int s=0; s<w; s++){
			int offset = s<<(h-ph+1);
			for(int i=0; i<p; i++){
				long l = a[i+offset],
					 r = a[i+offset+p];
				a[i+offset] = (l + r) % mod;
				a[i+offset+p] = (l - r + mod) * inow % mod;
			}
			inow = inow * sum_ie[__builtin_ctz(~s)] % mod;
		}
	}
}

long *convolution(long a[], int n, long b[], int m){
	int t = 0;
	while(n+m-1 > (1<<t))t++;
	if(t > 26)exit(1);
	long *c = (long*)calloc(1<<t, sizeof(long));
	memcpy(c, a, sizeof(long) * n);
	long *d = (long*)calloc(1<<t, sizeof(long));
	memcpy(d, b, sizeof(long) * m);
	butterfly(c, t); butterfly(d, t);
	for(int i=0; i<(1<<t); i++)c[i] = c[i] * d[i] % mod;
	free(d);
	butterfly_inv(c, t);
	long inv = modpow(1<<t, mod-2, mod);
	for(int i=0; i<(1<<t); i++)c[i] = c[i] * inv % mod;
	return c;
}

long A[1<<19], B[1<<19];
int main(){
	int N = nextint(), M = nextint();
	for(int i=0; i<N; i++)A[i] = nextint();
	for(int i=0; i<M; i++)B[i] = nextint();
	long *C = convolution(A, N, B, M);
	for(int i=0; i<N+M-1; i++){
		if(i)putchar(32);
		printf("%ld", C[i]);
	}putchar(10);
	return 0;
}