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 with AC Library v1.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define int long long
#define ull unsigned long long
#define ld long double
#define rep(a) rep1(i,a)
#define rep1(i,a) rep2(i,0,a)
#define rep2(i,b,a) for(int i=(b); i<((int)(a)); i++)
#define rep3(i,b,a) for(int i=(b); i>=((int)(a)); i--)
#define all(a) a.begin(),a.end()
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
//#define inf 2000000000
#define inf 8000000000000000000
#define eps 1e-9
#define sz(a) ((int)a.size())
#define pow2(x) (1ll<<(x))
#define ceiling(a,b) (((a)+(b)-1)/(b))
#define print0(a) cout << (a) << ' '
#define print1(a) cout << (a) << '\n'
#define print2(a,b) cout << (a) << ' ',print1(b)
#define print3(a,b,c) cout << (a) << ' ',print2(b,c)
#define print4(a,b,c,d) cout << (a) << ' ',print3(b,c,d)
#define ykh mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define ordered_set tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>

using namespace std;
using namespace __gnu_pbds;

const int Mod=1000000007,Mod2=998244353;
const int MOD=Mod2;
const int maxn=pow2(19)+5;
//i_am_noob
int n,m,x;

template <int mod>
struct Modint{
    int val;
    Modint(int _val=0){val=_val;}
    operator int() const {return (*this).val;}
    Modint operator +(const Modint& o) const {return val+o.val>=mod?Modint(val+o.val-mod):Modint(val+o.val);}
    Modint operator -() const {return val?Modint(mod-val):*this;}
    Modint operator -(const Modint& o) const {return val-o.val<0?Modint(val-o.val+mod):Modint(val-o.val);}
    Modint operator *(const Modint& o) const {return Modint(val*o.val%mod);}
    Modint operator +=(const Modint& o){*this=(*this)+o;return *this;}
    Modint operator -=(const Modint& o){*this=(*this)-o;return *this;}
    Modint operator *=(const Modint& o){*this=(*this)*o;return *this;}
    Modint Pow(int b) const {
        Modint tmp(val),ret(1);
        while(b){
            if(b&1) ret*=tmp;
            b>>=1;tmp*=tmp;
        }
        return ret;
    }
    Modint Pow(const Modint& a, int b) const {return a.Pow(b);}
    inline Modint inv() const {return (*this).Pow(mod-2);}
    Modint operator /(const Modint& o) const {return *this*o.inv();}
    bool operator ==(const Modint& o) const {return val==o.val;}
};
#define modint Modint<MOD>

template <typename T>
struct FFT{
    int siz;
    vector<T> rt,rev_rt;
    T inv_siz;
    FFT(int _siz){
        siz=_siz;
        T x=T(3).Pow((MOD-1)>>_siz);
        rep(pow2(_siz)) rt.pb(i?rt.back()*x:T(1));
        rep(pow2(_siz)) rev_rt.pb(i?rt[pow2(_siz)-i]:T(1));
        inv_siz=T(pow2(siz)).inv();
    }
    void mul_matrix(vector<T>& vec, vector<T>& RT){
        vec.resize(pow2(siz));
        int rev=0;
        rep(pow2(siz)){
            if(i>rev) swap(vec[i],vec[rev]);
            for(int j=pow2(siz-1); (rev^=j)<j; j>>=1);
        }
        T tmp;
        rep2(layer,1,siz+1) for(int i=0; i<pow2(siz); i+=pow2(layer)) for(int j=i; j<i+pow2(layer-1); j++){
            tmp=RT[(j-i)<<(siz-layer)]*vec[j+pow2(layer-1)];
            vec[j+pow2(layer-1)]=vec[j]-tmp;
            vec[j]=vec[j]+tmp;
        }
    }
    void mul(vector<T>& vec1, vector<T>& vec2, vector<T>& ans){
        mul_matrix(vec1,rt),mul_matrix(vec2,rt);
        ans.resize(pow2(siz));
        rep(pow2(siz)) ans[i]=vec1[i]*vec2[i];
        mul_matrix(ans,rev_rt);
        rep(pow2(siz)) ans[i]=ans[i]*inv_siz;
    }
};

FFT<modint> fft(20);
vector<modint> vec1,vec2,vec3;

signed main(){
    ios_base::sync_with_stdio(0),cin.tie(0);
    cin >> n >> m;
    rep(n){
        cin >> x;
        vec1.pb(x);
    }
    rep(m){
        cin >> x;
        vec2.pb(x);
    }
    fft.mul(vec1,vec2,vec3);
    rep(n+m-1) print0(vec3[i]);
    cout << "\n";
    return 0;
}