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>
#define ll long long
#define rep(i,l,r)for(ll i=(l);i<(r);i++)
ll pom(ll a,ll n,int m){ll x=1;for(a%=m;n;n/=2)n&1?x=x*a%m:0,a=a*a%m;return x;}
#define invp(a,p)pom(a,p-2,p)

#define p 998244353

//非再帰fft
void fft(ll*a,int n,ll g){
	for(int block=n;block>=2;block/=2){
		ll gi=1;
		for(int i=0;i<block/2;i++){
			for(int start=0;start<n;start+=block){
				//a[start+i]とa[start+i+block/2]を合体
				int temp=a[start+i]-a[start+i+block/2];
				a[start+i]+=a[start+i+block/2];
				if(a[start+i]>=p)a[start+i]-=p;
				a[start+i+block/2]=(temp+p)*gi%p;
			}
			gi=gi*g%p;
		}
        g=g*g%p;
	}

	//bit reverse
	int i=0;
	rep(j,1,n-1){
		for(int k=n>>1;k>(i^=k);k>>=1);//rev(i)に2進の+1をやる気持ち
		if(j<i){int t=a[j];a[j]=a[i];a[i]=t;}
    }
}

ll*comb(ll*a,int n,ll*b,int m){
	//0詰め
	int t=1;
	while(n+m-1>t)t*=2;
	if(t>(1<<26)){puts("error");exit(0);}
	ll*c=(ll*)calloc(t,sizeof(ll));
	memcpy(c,a,n*sizeof(ll));
	ll*d=(ll*)calloc(t,sizeof(ll));
	memcpy(d,b,m*sizeof(ll));
	//fft
	ll g=pom(3,(p-1)/t,p);
	fft(c,t,g);
	fft(d,t,g);
	//掛け算
	rep(i,0,t)c[i]=c[i]*d[i]%p;
	free(d);
	//復元
	fft(c,t,invp(g,p));
	ll coef=invp(t,p);
	rep(i,0,t)c[i]=c[i]*coef%p;
	return c;
}

ll a[1<<19],b[1<<19];
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	rep(i,0,n)scanf("%lld",a+i);
	rep(i,0,m)scanf("%lld",b+i);
	ll*c=comb(a,n,b,m);
	rep(i,0,n+m-1)printf("%lld ",c[i]);
}