(in-package :cl-user)
(eval-when (:compile-toplevel :load-toplevel :execute)
  (sb-int:defconstant-eqx opt
    #+swank '(optimize (speed 3) (safety 2))
    #-swank '(optimize (speed 3) (safety 0) (debug 0))
    #'equal)
  #+swank (ql:quickload '(:cl-debug-print :fiveam) :silent t)
  #-swank (set-dispatch-macro-character
           #\# #\> (lambda (s c p) (declare (ignore c p)) `(values ,(read s nil nil t)))))
#+swank (set-dispatch-macro-character #\# #\> #'cl-debug-print:debug-print-reader)

(macrolet ((def-int (b)
             `(progn (deftype ,(intern (format nil "UINT~A" b)) () '(unsigned-byte ,b))
                     (deftype ,(intern (format nil "INT~A" b)) () '(signed-byte ,b))))
           (defs (&rest bits) `(progn ,@(mapcar (lambda (b) `(def-int ,b)) bits))))
  (defs 2 4 7 8 15 16 31 32 62 63 64))

(defconstant +mod+ 998244353)

(defmacro dbg (&rest forms)
  #+swank (if (= (length forms) 1)
              `(format *error-output* "~A => ~A~%" ',(car forms) ,(car forms))
              `(format *error-output* "~A => ~A~%" ',forms `(,,@forms)))
  #-swank (declare (ignore forms)))

(declaim (inline println))
(defun println (obj &optional (stream *standard-output*))
  (let ((*read-default-float-format* 'double-float))
    (prog1 (princ obj stream) (terpri stream))))

;; BEGIN_INSERTED_CONTENTS
;;;
;;; Arithmetic operations with static modulus
;;;

(defpackage :cp/mod-operations
  (:use :cl)
  (:export #:define-mod-operations))
(in-package :cp/mod-operations)

;; NOTE: Currently MOD* and MOD+ doesn't apply MOD when the number of
;; parameters is one. For simplicity I won't fix it for now.
(defmacro define-mod-operations (divisor &optional (package (sb-int:sane-package)))
  (let ((mod* (intern "MOD*" package))
        (mod+ (intern "MOD+" package))
        (incfmod (intern "INCFMOD" package))
        (decfmod (intern "DECFMOD" package))
        (mulfmod (intern "MULFMOD" package)))
    `(progn
       (defun ,mod* (&rest args)
         (reduce (lambda (x y) (mod (* x y) ,divisor)) args))

       (defun ,mod+ (&rest args)
         (reduce (lambda (x y) (mod (+ x y) ,divisor)) args))

       #+sbcl
       (eval-when (:compile-toplevel :load-toplevel :execute)
         (locally (declare (sb-ext:muffle-conditions warning))
           (sb-c:define-source-transform ,mod* (&rest args)
             (if (null args)
                 1
                 (reduce (lambda (x y) `(mod (* ,x ,y) ,',divisor)) args)))
           (sb-c:define-source-transform ,mod+ (&rest args)
             (if (null args)
                 0
                 (reduce (lambda (x y) `(mod (+ ,x ,y) ,',divisor)) args)))))

       (define-modify-macro ,incfmod (delta)
         (lambda (x y) (mod (+ x y) ,divisor)))

       (define-modify-macro ,decfmod (delta)
         (lambda (x y) (mod (- x y) ,divisor)))

       (define-modify-macro ,mulfmod (multiplier)
         (lambda (x y) (mod (* x y) ,divisor))))))

(define-mod-operations cl-user::+mod+ :cl-user)

;;;
;;; Fast Number Theoretic Transform
;;; Reference:
;;; https://github.com/ei1333/library/blob/master/math/fft/number-theoretic-transform-friendly-mod-int.cpp
;;;

(defpackage :cp/ntt
  (:use :cl)
  (:export #:define-ntt #:check-ntt-vector #:ntt-int #:ntt-vector #:+ntt-mod+))
(in-package :cp/ntt)

(deftype ntt-int () '(unsigned-byte 31))
(deftype ntt-vector () '(simple-array ntt-int (*)))

(eval-when (:compile-toplevel :load-toplevel :execute)
  (declaim (inline %tzcount))
  (defun %tzcount (x)
    "Returns the number of trailing zero bits. Note that (%TZCOUNT 0) = -1."
    (- (integer-length (logand x (- x))) 1))
  (defun %mod-power (base exp modulus)
    (declare (ntt-int base exp modulus))
    (let ((res 1))
      (declare (ntt-int res))
      (loop while (> exp 0)
            when (oddp exp)
            do (setq res (mod (* res base) modulus))
            do (setq base (mod (* base base) modulus)
                     exp (ash exp -1)))
      res))
  (defun %mod-inverse (x modulus)
    (%mod-power x (- modulus 2) modulus))
  (defun %calc-generator (modulus)
    "MODULUS must be prime."
    (declare (ntt-int modulus))
    (assert (>= modulus 2))
    (case modulus
      (2 1)
      (167772161 3)
      (469762049 3)
      (754974721 11)
      (998244353 3)
      (otherwise
       (let ((divs (make-array 20 :element-type 'ntt-int :initial-element 0))
             (count 1)
             (x (floor (- modulus 1) 2)))
         (declare ((integer 0 #.most-positive-fixnum) x))
         (setf (aref divs 0) 2)
         (loop while (evenp x)
               do (setq x (floor x 2)))
         (loop for i of-type ntt-int from 3 by 2
               while (<= (* i i) x)
               when (zerop (mod x i))
               do (setf (aref divs count) i)
                  (incf count)
                  (loop while (zerop (mod x i))
                        do (setq x (floor x i))))
         (when (> x 1)
           (setf (aref divs count) x)
           (incf count))
         (loop for g of-type ntt-int from 2
               for ok = t
               do (dotimes (i count)
                    (when (= 1 (%mod-power g (floor (- modulus 1) (aref divs i)) modulus))
                      (setq ok nil)
                      (return)))
               when ok
               do (return g)))))))

;; KLUDGE: This function depends on SBCL's behaviour. Actually ADJUST-ARRAY
;; isn't guaranteed to preserve the given VECTOR.
(declaim (ftype (function * (values ntt-vector &optional)) %adjust-array))
(defun %adjust-array (vector length)
  (declare (vector vector))
  (let ((vector (coerce vector 'ntt-vector)))
    (if (= (length vector) length)
        (copy-seq vector)
        (adjust-array vector length :initial-element 0))))

(defun check-ntt-vector (vector)
  (declare (optimize (speed 3))
           (vector vector))
  (let ((len (length vector)))
    (assert (zerop (logand len (- len 1)))) ;; power of two
    (check-type len ntt-int)))

(defmacro define-ntt (modulus &key ntt inverse-ntt convolve mod-inverse mod-power)
  (let* ((ntt (or ntt (intern "NTT!")))
         (inverse-ntt (or inverse-ntt (intern "INVERSE-NTT!")))
         (convolve (or convolve (intern "CONVOLVE")))
         (mod-power (or mod-power (gensym "MOD-POWER")))
         (mod-inverse (or mod-inverse (gensym "MOD-INVERSE")))
         (ntt-base (gensym "*NTT-BASE*"))
         (ntt-inv-base (gensym "*NTT-INV-BASE*"))
         (base-size (%tzcount (- modulus 1)))
         (root (%calc-generator modulus)))
    (assert (typep modulus 'ntt-int))
    `(progn
       (declaim (inline ,mod-power))
       (defun ,mod-power (base exp)
         (declare (ntt-int base)
                  ((integer 0 #.most-positive-fixnum) exp))
         (let ((res 1))
           (declare (ntt-int res))
           (loop while (> exp 0)
                 when (oddp exp)
                 do (setq res (mod (* res base) ,modulus))
                 do (setq base (mod (* base base) ,modulus)
                          exp (ash exp -1)))
           res))
       (declaim (inline ,mod-inverse))
       (defun ,mod-inverse (x)
         (,mod-power x (- ,modulus 2)))
       (declaim (ntt-vector ,ntt-base ,ntt-inv-base))
       (sb-ext:define-load-time-global ,ntt-base
         (make-array ,base-size :element-type 'ntt-int))
       (sb-ext:define-load-time-global ,ntt-inv-base
         (make-array ,base-size :element-type 'ntt-int))
       (dotimes (i ,base-size)
         (setf (aref ,ntt-base i)
               (mod (- (%mod-power ,root (ash (- ,modulus 1) (- (+ i 2))) ,modulus))
                    ,modulus)
               (aref ,ntt-inv-base i)
               (%mod-inverse (aref ,ntt-base i) ,modulus)))

       (declaim (ftype (function * (values ntt-vector &optional)) ,ntt))
       (defun ,ntt (vector)
         (declare (optimize (speed 3) (safety 0))
                  (vector vector))
         (check-ntt-vector vector)
         (labels ((mod* (x y) (mod (* x y) ,modulus))
                  (mod+ (x y)
                    (let ((res (+ x y)))
                      (if (>= res ,modulus)
                          (- res ,modulus)
                          res)))
                  (mod- (x y) (mod+ x (- ,modulus y))))
           (declare (inline mod* mod+ mod-))
           (let* ((vector (coerce vector 'ntt-vector))
                  (len (length vector))
                  (base ,ntt-base))
             (declare (ntt-vector vector base)
                      (ntt-int len))
             (when (<= len 1)
               (return-from ,ntt vector))
             (loop for m of-type ntt-int = (ash len -1) then (ash m -1)
                   while (> m 0)
                   for w of-type ntt-int = 1
                   for k of-type ntt-int = 0
                   do (loop for s of-type ntt-int from 0 below len by (* 2 m)
                            do (loop for i from s below (+ s m)
                                     for j from (+ s m)
                                     for x = (aref vector i)
                                     for y = (mod* (aref vector j) w)
                                     do (setf (aref vector i) (mod+ x y)
                                              (aref vector j) (mod- x y)))
                               (incf k)
                               (setq w (mod* w (aref base (%tzcount k))))))
             vector)))

       (declaim (ftype (function * (values ntt-vector &optional)) ,inverse-ntt))
       (defun ,inverse-ntt (vector &optional inverse)
         (declare (optimize (speed 3) (safety 0))
                  (vector vector))
         (check-ntt-vector vector)
         (labels ((mod* (x y)
                    (declare (ntt-int x y))
                    (mod (* x y) ,modulus))
                  (mod+ (x y)
                    (declare (ntt-int x y))
                    (let ((res (+ x y)))
                      (if (>= res ,modulus)
                          (- res ,modulus)
                          res)))
                  (mod- (x y)
                    (declare (ntt-int x y))
                    (mod+ x (- ,modulus y))))
           (declare (inline mod* mod+ mod-))
           (let* ((vector (coerce vector 'ntt-vector))
                  (len (length vector))
                  (base ,ntt-inv-base))
             (declare (ntt-vector vector base)
                      (ntt-int len))
             (when (<= len 1)
               (return-from ,inverse-ntt vector))
             (loop for m of-type ntt-int = 1 then (ash m 1)
                   while (< m len)
                   for w of-type ntt-int = 1
                   for k of-type ntt-int = 0
                   do (loop for s of-type ntt-int from 0 below len by (* 2 m)
                            do (loop for i from s below (+ s m)
                                     for j from (+ s m)
                                     for x = (aref vector i)
                                     for y = (aref vector j)
                                     do (setf (aref vector i) (mod+ x y)
                                              (aref vector j) (mod* (mod- x y) w)))
                               (incf k)
                               (setq w (mod* w (aref base (%tzcount k))))))
             (when inverse
               (let ((inv-len (,mod-power len (- ,modulus 2))))
                 (dotimes (i len)
                   (setf (aref vector i) (mod* inv-len (aref vector i))))))
             vector)))

       (declaim (ftype (function * (values ntt-vector &optional)) ,convolve))
       (defun ,convolve (vector1 vector2)
         (declare (optimize (speed 3))
                  (vector vector1 vector2))
         (let ((len1 (length vector1))
               (len2 (length vector2)))
           (when (or (zerop len1) (zerop len2))
             (return-from ,convolve (make-array 0 :element-type 'ntt-int)))
           (let* ((mul-len (max 0 (- (+ len1 len2) 1)))
                  ;; power of two ceiling
                  (required-len (ash 1 (integer-length (max 0 (- mul-len 1)))))
                  (vector1 (,ntt (%adjust-array vector1 required-len)))
                  (vector2 (,ntt (%adjust-array vector2 required-len))))
             (declare ((mod #.array-total-size-limit) mul-len))
             (dotimes (i required-len)
               (setf (aref vector1 i)
                     (mod (* (aref vector1 i) (aref vector2 i)) ,modulus)))
             (adjust-array (,inverse-ntt vector1 t) mul-len)))))))

(eval-when (:compile-toplevel :load-toplevel :execute)
  (defconstant +ntt-mod+ 998244353))

#+(or)
(define-ntt #.+ntt-mod+)

(defpackage :cp/polynomial-ntt
  (:use :cl :cp/ntt)
  (:export #:poly-multiply #:poly-inverse #:poly-floor #:poly-mod #:poly-sub #:poly-add #:multipoint-eval))
(in-package :cp/polynomial-ntt)

(define-ntt #.+ntt-mod+
  :convolve poly-multiply
  :mod-inverse %mod-inverse)

(declaim (ftype (function * (values ntt-vector &optional)) poly-inverse))
(defun poly-inverse (poly &optional result-length)
  (declare (optimize (speed 3))
           (vector poly)
           ((or null fixnum) result-length))
  (let* ((poly (coerce poly 'ntt-vector))
         (n (length poly)))
    (declare (ntt-vector poly))
    (when (or (zerop n)
              (zerop (aref poly 0)))
      (error 'division-by-zero
             :operation #'poly-inverse
             :operands poly))
    (let ((res (make-array 1
                           :element-type 'ntt-int
                           :initial-element (%mod-inverse (aref poly 0))))
          (result-length (or result-length n)))
      (declare (ntt-vector res))
      (loop for i of-type ntt-int = 1 then (ash i 1)
            while (< i result-length)
            for decr = (poly-multiply (poly-multiply res res)
                                      (subseq poly 0 (min (length poly) (* 2 i))))
            for decr-len = (length decr)
            do (setq res (adjust-array res (* 2 i) :initial-element 0))
               (dotimes (j (* 2 i))
                 (setf (aref res j)
                       (mod (the ntt-int
                                 (+ (mod (* 2 (aref res j)) +ntt-mod+)
                                    (if (>= j decr-len) 0 (- +ntt-mod+ (aref decr j)))))
                            +ntt-mod+))))
      (adjust-array res result-length))))

(declaim (ftype (function * (values ntt-vector &optional)) poly-floor))
(defun poly-floor (poly1 poly2)
  (declare (optimize (speed 3))
           (vector poly1 poly2))
  (let* ((poly1 (coerce poly1 'ntt-vector))
         (poly2 (coerce poly2 'ntt-vector))
         (deg1 (+ 1 (or (position 0 poly1 :from-end t :test-not #'eql) -1)))
         (deg2 (+ 1 (or (position 0 poly2 :from-end t :test-not #'eql) -1))))
    (when (> deg2 deg1)
      (return-from poly-floor (make-array 0 :element-type 'ntt-int)))
    (setq poly1 (nreverse (subseq poly1 0 deg1))
          poly2 (nreverse (subseq poly2 0 deg2)))
    (let* ((res-len (+ 1 (- deg1 deg2)))
           (res (adjust-array (poly-multiply poly1 (poly-inverse poly2 res-len))
                              res-len)))
      (nreverse res))))

(declaim (ftype (function * (values ntt-vector &optional)) poly-sub))
(defun poly-sub (poly1 poly2)
  (declare (optimize (speed 3))
           (vector poly1 poly2))
  (let* ((poly1 (coerce poly1 'ntt-vector))
         (poly2 (coerce poly2 'ntt-vector))
         (len (max (length poly1) (length poly2)))
         (res (make-array len :element-type 'ntt-int :initial-element 0)))
    (replace res poly1)
    (dotimes (i (length poly2))
      (let ((value (+ (aref res i)
                      (the ntt-int (- +ntt-mod+ (aref poly2 i))))))
        (setf (aref res i)
              (if (>= value +ntt-mod+)
                  (- value +ntt-mod+)
                  value))))
    res))

(declaim (ftype (function * (values ntt-vector &optional)) poly-add))
(defun poly-add (poly1 poly2)
  (declare (optimize (speed 3))
           (vector poly1 poly2))
  (let* ((poly1 (coerce poly1 'ntt-vector))
         (poly2 (coerce poly2 'ntt-vector))
         (len (max (length poly1) (length poly2)))
         (res (make-array len :element-type 'ntt-int :initial-element 0)))
    (replace res poly1)
    (dotimes (i (length poly2))
      (let ((value (+ (aref res i) (aref poly2 i))))
        (setf (aref res i)
              (if (>= value +ntt-mod+)
                  (- value +ntt-mod+)
                  value))))
    res))

(declaim (ftype (function * (values ntt-vector &optional)) poly-mod))
(defun poly-mod (poly1 poly2)
  (declare (optimize (speed 3))
           (vector poly1 poly2))
  (let ((poly1 (coerce poly1 'ntt-vector))
        (poly2 (coerce poly2 'ntt-vector)))
    (when (loop for x across poly1 always (zerop x))
      (return-from poly-mod (make-array 0 :element-type 'ntt-int)))
    (let* ((res (poly-sub poly1 (poly-multiply (poly-floor poly1 poly2) poly2)))
           (end (+ 1 (or (position 0 res :from-end t :test-not #'eql) -1))))
      (subseq res 0 end))))

(declaim (ftype (function * (values ntt-vector &optional)) multipoint-eval))
(defun multipoint-eval (poly points)
  (declare (optimize (speed 3))
           (vector poly points)
           #+sbcl (sb-ext:muffle-conditions style-warning))
  (check-ntt-vector points)
  (let* ((poly (coerce poly 'ntt-vector))
         (points (coerce points 'ntt-vector))
         (len (length points))
         (table (make-array (max 0 (- (* 2 len) 1)) :element-type 'ntt-vector))
         (res (make-array len :element-type 'ntt-int)))
    (unless (zerop len)
      (sb-int:named-let %build ((l 0) (r len) (pos 0))
        (declare ((integer 0 #.most-positive-fixnum) l r pos))
        (if (= (- r l) 1)
            (let ((lin (make-array 2 :element-type 'ntt-int)))
              (setf (aref lin 0) (- +ntt-mod+ (aref points l)) ;; NOTE: non-zero
                    (aref lin 1) 1)
              (setf (aref table pos) lin))
            (let ((mid (ash (+ l r) -1)))
              (%build l mid (+ 1 (* pos 2)))
              (%build mid r (+ 2 (* pos 2)))
              (setf (aref table pos)
                    (poly-multiply (aref table (+ 1 (* pos 2)))
                                   (aref table (+ 2 (* pos 2))))))))
      (sb-int:named-let %eval ((poly poly) (l 0) (r len) (pos 0))
        (declare ((integer 0 #.most-positive-fixnum) l r pos))
        (if (= (- r l) 1)
            (let ((tmp (poly-mod poly (aref table pos))))
              (setf (aref res l) (if (zerop (length tmp)) 0 (aref tmp 0))))
            (let ((mid (ash (+ l r) -1)))
              (%eval (poly-mod poly (aref table (+ (* 2 pos) 1))) l mid (+ (* 2 pos) 1))
              (%eval (poly-mod poly (aref table (+ (* 2 pos) 2))) mid r (+ (* 2 pos) 2))))))
    res))

;; BEGIN_USE_PACKAGE
(eval-when (:compile-toplevel :load-toplevel :execute)
  (use-package :cp/polynomial-ntt :cl-user))
(eval-when (:compile-toplevel :load-toplevel :execute)
  (use-package :cp/mod-operations :cl-user))
(in-package :cl-user)

;;;
;;; Body
;;;

(defun main ()
  (let* ((n (read))
         (k (read))
         (poly (make-array (+ n 1) :element-type 'uint31 :initial-element 0)))
    (declare (uint31 n k))
    (dotimes (_ k)
      (let ((l (read))
            (r (read)))
        (loop for i from l to r
              do (setf (aref poly i) 1))))
    (let ((res (poly-inverse (poly-sub #(1) poly))))
      (println (aref res (- n 1))))))

#-swank (main)

;;;
;;; Test and benchmark
;;;

#+swank
(defun get-clipbrd ()
  (with-output-to-string (out)
    #+os-windows (run-program "powershell.exe" '("-Command" "Get-Clipboard") :output out :search t)
    #+os-unix (run-program "xsel" '("-b" "-o") :output out :search t)))

#+swank (defparameter *this-pathname* (uiop:current-lisp-file-pathname))
#+swank (defparameter *dat-pathname* (uiop:merge-pathnames* "test.dat" *this-pathname*))

#+swank
(defun run (&optional thing (out *standard-output*))
  "THING := null | string | symbol | pathname

null: run #'MAIN using the text on clipboard as input.
string: run #'MAIN using the string as input.
symbol: alias of FIVEAM:RUN!.
pathname: run #'MAIN using the text file as input."
  (let* ((*standard-output* (or out (make-string-output-stream)))
         (res (etypecase thing
                (null
                 (with-input-from-string (*standard-input* (delete #\Return (get-clipbrd)))
                   (main)))
                (string
                 (with-input-from-string (*standard-input* (delete #\Return thing))
                   (main)))
                (symbol (5am:run! thing))
                (pathname
                 (with-open-file (*standard-input* thing)
                   (main))))))
    (if out res (get-output-stream-string *standard-output*))))

#+swank
(defun gen-dat ()
  (uiop:with-output-file (out *dat-pathname* :if-exists :supersede)
    (format out "")))

#+swank
(defun bench (&optional (out (make-broadcast-stream)))
  (time (run *dat-pathname* out)))

#-swank
(eval-when (:compile-toplevel)
  (when (and (boundp 'sb-c::*compiler-warning-count*)
             (> sb-c::*compiler-warning-count* 0))
    (sb-ext:quit :unix-status 1)))

;; To run: (5am:run! :sample)
#+swank
(it.bese.fiveam:test :sample
  (5am:is
   (equal "4
"
          (run "5 2
1 1
3 4
" nil)))
  (5am:is
   (equal "0
"
          (run "5 2
3 3
5 5
" nil)))
  (5am:is
   (equal "5
"
          (run "5 1
1 2
" nil)))
  (5am:is
   (equal "221823067
"
          (run "60 3
5 8
1 3
10 15
" nil))))


Measured memory_bytes: 49928