#include <iostream> //allow input output
#define ll long long //ll now means long long, thus we don't type long long each time
using namespace std; //we don't need to use std::
//blank line
//another blank line because why not
ll fastpow(ll a, ll b, ll mod){//this is a fastpow method, computes a^b mod mod
ll cur = 1;//If k is the # of itrs in the while loop, a^(b%2^k)
ll p2p = a;//a^(2^k)
while(b != 0){//we stop when b = 0
if(b%2 == 1){//we need to multiply cur by p2p when this bit is 1
cur *= p2p;//we multiply cur by a^(2^k)
cur = cur%mod;//we mod cur to avoid overflow stuff
}//end if statment
p2p *= p2p;//we square p2p to ready the next itr of the loop
p2p = p2p%mod;//we mod p2p to avoid overflow stuff
b = b/2;//shift b 1 bit back for the next itr
}//end while loop
return cur;//return the answer
}//end fastpow
//blank line
//another blank line because why not
void ntt(ll* a, ll* x, ll* r, ll n, ll mod){//this finds a(x) for all primitive roots, which are stored in x.
//r[i] is the reverse of the binary string of i, n is the size of a, mod is the mod we are taking everything
for(int i = 0; i < (1 << n); i++){//a for loop going from 0 - 2^n-1, this takes care of base cases
if(i < r[i]){//We don't want to swap twice
swap(a[i],a[r[i]]);//we take care of all the base cases by setting ans[i] = a[r[i]], but we use the a as the ans array
}//end if statement
}//end for loop
//blank line
for(int i = 1; i <= n; i++){//a for loop going from 1 - n, this solves each "layer"
for(int j = 0; j < (1 << n); j+=(1 << i)){//j enumerates through each subproblem block, for example, [0 2 4 6] is a [1 3 5 7]
for(int k = 0; k < (1 << (i-1)); k++){//we enumerate through the 2 halves of each subproblem block and combine them
ll x1 = a[j+k] + x[(1 << n)/(1 << i) * k] * a[j+k+(1 << (i-1))];//We use A(x) = Aeven(x^2) + x * Aodd(x^2), so we compute them for every (2^i)th root
ll x2 = a[j+k] + x[(1 << n)/(1 << i) * (k + (1 << (i-1)))] * a[j+k+(1 << (i-1))];//we do a similar thing for the other root
a[j+k] = x1%mod;//we take mod, and we can replace a with the value, since the old values won't the used again
a[j+k+(1 << (i-1))] = x2%mod;//same as last line
}//end for loop
}//end for loop
}//end for loop
//blank line
//another blank line because why not
}//end ntt method.
//blank line
//another blank line because why not
ll* mul(ll* a, ll* b, ll* c, ll n, ll g, ll mod){//This method multiplies a and b and puts the
//result in c. n is a power of 2 larger than a and b's degree, g is a primitive root of mod, and
// mod is the mod we are taking
n++;//we increase n, since we actually need 1 more
// cout << n << " " << endl;
ll r [(1 << n)];//this stores the reverse binary of every number 4 -> 100 -> 001 -> 1
//however, everything is padded so it has n digits
r[0] = 0;//base case
for(int i = 1; i < (1 << n); i++){//a for loop to compute r[x] for the rest of the nums
if(i%2 != 0){//the last digit is a 1
r[i] = (r[i/2]/2) + (1 << (n-1));//we add (1 << (n-1)) to the front
}else{// the last digit is a 0
r[i] = (r[i/2]/2);//we take r[i/2], and divide by 2 since there is an extra 0
}//end if else
}//end for loop
ll x1 [(1 << n)];//the 2^n th roots of unity
x1[0] = 1;//0th root of unity is always 0
ll rt = fastpow(g, (mod-1)/(1 << n), mod);//we raise the primitive root to a power
//to obtain the first 2^nth root of unity
for(int i = 1; i < (1 << n); i++){//for loop
x1[i] = (rt * x1[i-1])%mod;//we manually compute each root of unity
}//end for loop
ll x2 [(1 << n)];//the 2^n th roots of unity, but backwards (These are actually the -xth 2^nth root of unity)
x2[0] = 1;//we set 0th root of unity to 0
for(int i = 1; i < (1 << n); i++){//for loop
x2[i] = x1[(1 << n) - i];//the -xth root of unity is equal to the n-xth root of unity
}//end for loop
ntt(a, x1, r, n, mod);// we do ntt on a to find a's point form
ntt(b, x1, r, n, mod);// we do ntt on b to find b's point form
for(int i = 0; i < (1 << n); i++){//for loop
c[i] = (a[i] * b[i])%mod;//we find the point form of c
}//end for loop
ntt(c, x2, r, n, mod);//we do an inverse ntt on c to find c's coefficient form.
//we use x2 for this since the inverse is basically the same except we use x^-n as coeffs
ll inverse = fastpow((1 << n), mod-2, mod);//we need to divide by 2^n at the end
//blank line
for(int i = 0; i < (1 << n); i++){//for loop
c[i] = (c[i] * inverse)%mod;//we divide the coeffs by 2^n since we are doing ifft
}//end for loop
return c;//the coefficients of the multiplied poly is returned
}//end mul function
//blank line
int main() {//main function
int n;//degree of n
int m;//degree of m
cin >> n >> m;//n and m
int x = max(n,m)+1;//the highest number of terms in either n and m
int p2 = 1;//this finds 1 + power of 2 higher than n and m
while(x != 0){//while loop, pushes x until it gets to 0
x = x/2;//we divide x by 2
p2++;//we increase p2
}//end while loop
ll a [(1 << p2)];//polynomial 1
ll b [(1 << p2)];//polynomial 2
ll c [(1 << p2)];//answer
for(int i = 0; i < (1 << p2); i++){//for loop
a[i] = 0;//init poly1 to 0
b[i] = 0;//init poly2 to 0s
c[i] = 0;//init ans to 0s (probably not needed)
}//end for loop
for(int i = 0; i <= n; i++){//for loop
cin >> a[i];//read in each elem of a
}//end for loop
for(int i = 0; i <= m; i++){//for loop
cin >> b[i];//read in each elem of b
}//end for loop
mul(a,b,c,p2-1,3,998244353);//we multiply a and b
for(int i = 0; i <= (n+m); i++){//for loop
cout << c[i] << " ";//print the result
}//end for loop
cout << "\n";//an extra endl since why not
}//end main