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 Ruby (2.7.1) (judge verdict: Time Limit Exceeded)

# frozen_string_literal: true

require 'numo/narray'

class Convolution
  def initialize(mod = 998244353, primitive_root = 3)
    @mod = mod
    @mod_narray = Numo::Int64[mod]

    cnt2 = bsf(@mod - 1)
    e = primitive_root.pow((@mod-1) >> cnt2, @mod)
    ie = e.pow(@mod - 2, @mod)
    
    es = [0]*(cnt2-1)
    ies = [0]*(cnt2-1)
    cnt2.downto(2){ |i|
      es[i-2] = e
      ies[i-2] = ie
      e = e*e % @mod
      ie = ie*ie % @mod
    }
    now = inow = 1

    @sum_e = [0]*(cnt2-2)
    @sum_ie = [0]*(cnt2-2)
    (cnt2-2).times{ |i|
      @sum_e[i] = es[i]*now % @mod
      now = now*ies[i] % @mod
      @sum_ie[i] = ies[i]*inow % @mod
      inow = inow*es[i] % @mod
    }
    @sum_e = Numo::Int64[@sum_e]
    @sum_ie = Numo::Int64[@sum_ie]
  end

  def convolution(input_a, input_b)
    n = input_a.size
    m = input_b.size
    return [] if n==0 || m==0

    h = (n+m-2).bit_length
    z = 1 << h

    a = Numo::Int64.zeros(z)
    a.store(input_a)
    b = Numo::Int64.zeros(z)
    b.store(input_b)

    batterfly(a, h)
    batterfly(b, h)

    a.inplace * b
    a.inplace % @mod_narray

    batterfly_inv(a, h)

    iz = z.pow(@mod-2, @mod)
    return a[0 .. n+m-2].to_a.map{ |a| a*iz % @mod }
  end

  def batterfly(a, h)
    1.upto(h){ |ph|
      w = 1 << (ph-1)
      p = 1 << (h-ph)
      now = Numo::Int64.ones(1)
      w.times{ |s|
        offset = s << (h-ph+1)
        l_range = offset ... offset+p
        r_range = offset+p ... offset+p+p
        l = a[l_range].copy
        r = a[r_range].copy*now
        a[l_range] = (l+r) % @mod_narray
        a[r_range] = (l-r) % @mod_narray
        now = now*@sum_e[bsf(~s)] % @mod_narray
      }
    }
  end

  def batterfly_inv(a, h)
    h.downto(1){ |ph|
      w = 1 << (ph-1)
      p = 1 << (h-ph)
      inow = Numo::Int64.ones(1)
      w.times{ |s|
        offset = s << (h-ph+1)
        l_range = offset ... offset+p
        r_range = offset+p ... offset+p+p
        l = a[l_range].copy
        r = a[r_range].copy
        a[l_range] = (l+r) % @mod_narray
        a[r_range] = (l-r)*inow % @mod_narray
        inow = inow*@sum_ie[bsf(~s)] % @mod_narray
      }
    }
  end

  def bsf(x)
    (x & -x).bit_length - 1
  end
  protected :batterfly, :batterfly_inv, :bsf
end

_, a, b = $<.map{ |e| e.split.map &:to_i }

conv = Convolution.new
puts conv.convolution(a, b).join(?\s)