#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