#line 1 "verify/yosupo/convolution/convolution_mod.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/convolution_mod"
#line 2 "template.hpp"
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define ALL(a) a.begin(),a.end()
#define RALL(a) a.rbegin(),a.rend()
#define SORT(a) sort(ALL(a))
#define RSORT(a) sort(RALL(a))
#define REV(a) reverse(ALL(a))
#define UNI(a) a.erase(unique(ALL(a)),a.end())
#define SZ(a) (int)(a.size())
#define LB(a,x) (int)(lower_bound(ALL(a),x)-a.begin())
#define UB(a,x) (int)(upper_bound(ALL(a),x)-a.begin())
#define MIN(a) *min_element(ALL(a))
#define MAX(a) *max_element(ALL(a))
using ll = long long;
using db = long double;
using i128 = __int128_t;
using u32 = uint32_t;
using u64 = uint64_t;
const int INF=INT_MAX/2;
const ll LINF=LLONG_MAX/4;
const db DINF=numeric_limits<db>::infinity();
const int MOD=998244353;
const int MOD2=1000000007;
const db EPS=1e-9;
const db PI=acos(db(-1));
template<class T>
using PQ = priority_queue<T,vector<T>,greater<T>>;
#define vv(T,a,n,...) vector<vector<T>> a(n,vector<T>(__VA_ARGS__))
#define vvv(T,a,n,m,...) vector<vector<vector<T>>> a(n,vector<vector<T>>(m,vector<T>(__VA_ARGS__)))
#define vvvv(T,a,n,m,k,...) vector<vector<vector<vector<T>>>> a(n,vector<vector<vector<T>>>(m,vector<vector<T>>(k,vector<T>(__VA_ARGS__))))
template<class T,class U>
bool chmin(T &a,U b){return b<a?a=b,1:0;}
template<class T,class U>
bool chmax(T &a,U b){return a<b?a=b,1:0;}
template<class T,class U>
T SUM(const U &a){return accumulate(ALL(a),T{});}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
mt19937_64 rng64(chrono::steady_clock::now().time_since_epoch().count());
#line 2 "modular-arithmetic/modint.hpp"
/**
* Author: Teetat T.
* Date: 2026-04-15
* Description: modular arithmetic operations
*/
template<int mod,int root=0>
struct ModInt{
using mint = ModInt;
static_assert(mod>0,"mod must be positive");
int x;
constexpr ModInt():x(0){}
constexpr ModInt(ll x):x((x%=mod)<0?x+mod:x){}
constexpr explicit operator int()const{return x;}
constexpr static int get_mod(){return mod;}
constexpr static mint get_root(){return mint(root);}
constexpr mint operator-()const{
mint res;
res.x=x?mod-x:0;
return res;
}
constexpr mint operator+()const{return *this;}
constexpr mint inv()const{
int a=x,b=mod,u=1,v=0,q=0;
while(b>0){
q=a/b;
swap(a-=q*b,b);
swap(u-=q*v,v);
}
return mint(u);
}
constexpr mint pow(ll n)const{
mint res=1,a=*this;
for(;n>0;a*=a,n>>=1)if(n&1)res*=a;
return res;
}
constexpr mint &operator+=(const mint &o){
if((x+=o.x)>=mod)x-=mod;
return *this;
}
constexpr mint &operator-=(const mint &o){
if((x-=o.x)<0)x+=mod;
return *this;
}
constexpr mint &operator*=(const mint &o){
x=(ll(x)*o.x)%mod;
return *this;
}
constexpr mint &operator/=(const mint &o){
return *this*=o.inv();
}
constexpr mint operator+(const mint &o)const{return mint(*this)+=o;}
constexpr mint operator-(const mint &o)const{return mint(*this)-=o;}
constexpr mint operator*(const mint &o)const{return mint(*this)*=o;}
constexpr mint operator/(const mint &o)const{return mint(*this)/=o;}
constexpr mint &operator++(){return *this+=mint(1);}
constexpr mint &operator--(){return *this-=mint(1);}
constexpr mint operator++(int){mint res=*this;*this+=mint(1);return res;}
constexpr mint operator--(int){mint res=*this;*this-=mint(1);return res;}
constexpr bool operator==(const mint &o)const{return x==o.x;}
constexpr bool operator!=(const mint &o)const{return x!=o.x;}
constexpr bool operator<(const mint &o)const{return x<o.x;}
friend istream &operator>>(istream &is,mint &o){ll x{};is>>x;o=mint(x);return is;}
friend ostream &operator<<(ostream &os,const mint &o){return os<<o.x;}
};
using mint998 = ModInt<998244353,3>;
using mint107 = ModInt<1000000007>;
#line 2 "modular-arithmetic/binpow.hpp"
/**
* Author: Teetat T.
* Date: 2024-01-15
* Description: n-th power using divide and conquer
* Time: $O(\log b)$
*/
template<class T>
constexpr T binpow(T a,ll b){
T res=1;
for(;b>0;b>>=1,a*=a)if(b&1)res*=a;
return res;
}
#line 3 "polynomial/ntt.hpp"
/**
* Author: Teetat T.
* Description: Number Theoretic Transform
* Time: $O(N \log N)$
*/
template<class mint>
struct NTT{
using vm = vector<mint>;
static constexpr mint root=mint::get_root();
static_assert(root!=0, "root must be nonzero");
static void ntt(vm &a){
int n=a.size(),L=31-__builtin_clz(n);
vm rt(n);
rt[1]=1;
for(int k=2,s=2;k<n;k*=2,s++){
mint z[]={1,binpow(root,MOD>>s)};
for(int i=k;i<2*k;i++)rt[i]=rt[i/2]*z[i&1];
}
vector<int> rev(n);
for(int i=1;i<n;i++)rev[i]=(rev[i/2]|(i&1)<<L)/2;
for(int i=1;i<n;i++)if(i<rev[i])swap(a[i],a[rev[i]]);
for(int k=1;k<n;k*=2)for(int i=0;i<n;i+=2*k)for(int j=0;j<k;j++){
mint z=rt[j+k]*a[i+j+k];
a[i+j+k]=a[i+j]-z;
a[i+j]+=z;
}
}
static vm conv(const vm &a,const vm &b){
if(a.empty()||b.empty())return {};
int s=a.size()+b.size()-1,n=1<<(32-__builtin_clz(s));
mint inv=mint(n).inv();
vm in1(a),in2(b),out(n);
in1.resize(n),in2.resize(n);
ntt(in1),ntt(in2);
for(int i=0;i<n;i++)out[-i&(n-1)]=in1[i]*in2[i]*inv;
ntt(out);
return vm(out.begin(),out.begin()+s);
}
vm operator()(const vm &a,const vm &b){
return conv(a,b);
}
};
#line 5 "verify/yosupo/convolution/convolution_mod.test.cpp"
using mint = mint998;
int main(){
cin.tie(nullptr)->sync_with_stdio(false);
int n,m;
cin >> n >> m;
vector<mint> a(n),b(m);
for(auto &x:a)cin >> x;
for(auto &x:b)cin >> x;
auto c=NTT<mint>()(a,b);
for(auto x:c)cout << x << " ";
cout << "\n";
}