(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)

(defpackage :cp/tzcount
  (:use :cl)
  (:export #:tzcount))
(in-package :cp/tzcount)

(declaim (inline tzcount))
(defun tzcount (x)
  "Returns the number of trailing zero bits. Note that (TZCOUNT 0) = -1."
  (- (integer-length (logand x (- x))) 1))

;;;
;;; 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 :cp/tzcount)
  (:export #:+ntt-mod+ #:ntt-int #:ntt-vector #:ntt! #:inverse-ntt! #:ntt-convolve
           #:check-ntt-vector #:%mod-inverse #:%mod-power))
(in-package :cp/ntt)

(defconstant +ntt-mod+ 998244353)
(defconstant +ntt-root+ 3)
(deftype ntt-int () '(unsigned-byte 31))
(deftype ntt-vector () '(simple-array ntt-int (*)))

(eval-when (:compile-toplevel :load-toplevel :execute)
  (assert (typep +ntt-mod+ 'ntt-int)))

(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) +ntt-mod+))
          do (setq base (mod (* base base) +ntt-mod+)
                   exp (ash exp -1)))
    res))

(declaim (inline %mod-inverse))
(defun %mod-inverse (x)
  (%mod-power x (- +ntt-mod+ 2)))

(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)))

(defun make-ntt-base ()
  (let* ((base-size (tzcount (- +ntt-mod+ 1)))
         (base (make-array base-size :element-type 'ntt-int))
         (inv-base (make-array base-size :element-type 'ntt-int)))
    (dotimes (i base-size)
      (setf (aref base i)
            (mod (- (%mod-power +ntt-root+ (ash (- +ntt-mod+ 1) (- (+ i 2)))))
                 +ntt-mod+)
            (aref inv-base i)
            (%mod-inverse (aref base i))))
    (values base inv-base)))

(defvar *ntt-base*)
(defvar *ntt-inv-base*)
(multiple-value-bind (base inv-base) (make-ntt-base)
  (setq *ntt-base* base)
  (setq *ntt-inv-base* inv-base))

(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) +ntt-mod+))
           (mod+ (x y)
             (let ((res (+ x y)))
               (if (>= res +ntt-mod+)
                   (- res +ntt-mod+)
                   res)))
           (mod- (x y) (mod+ x (- +ntt-mod+ y))))
    (declare (inline mod* mod+ mod-))
    (let* ((vector (coerce vector 'ntt-vector))
           (len (length vector))
           (base *ntt-base*))
      (declare ((simple-array ntt-int (*)) 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)))

(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) +ntt-mod+))
           (mod+ (x y)
             (declare (ntt-int x y))
             (let ((res (+ x y)))
               (if (>= res +ntt-mod+)
                   (- res +ntt-mod+)
                   res)))
           (mod- (x y)
             (declare (ntt-int x y))
             (mod+ x (- +ntt-mod+ y))))
    (declare (inline mod* mod+ mod-))
    (let* ((vector (coerce vector 'ntt-vector))
           (len (length vector))
           (base *ntt-inv-base*))
      (declare ((simple-array ntt-int (*)) 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 (- +ntt-mod+ 2))))
          (dotimes (i len)
            (setf (aref vector i) (mod* inv-len (aref vector i))))))
      vector)))

;; FIXME: Here I resort to 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))))

;; Change %ADJUST-ARRAY to ADJUST-ARRAY when if what you want is a destructive
;; operation.
(declaim (ftype (function * (values ntt-vector &optional)) ntt-convolve))
(defun ntt-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 ntt-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))))
      (dotimes (i required-len)
        (setf (aref vector1 i)
              (mod (* (aref vector1 i) (aref vector2 i)) +ntt-mod+)))
      (adjust-array (inverse-ntt! vector1 t) mul-len))))

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

;; TODO: utilize convolution as selectable module

(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 = (ntt-convolve (ntt-convolve 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 (ntt-convolve 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 (ntt-convolve (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)
                    (ntt-convolve (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/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: 49868