;; -*- coding: utf-8 -*-
(eval-when (:compile-toplevel :load-toplevel :execute)
  (defparameter OPT
    #+swank '(optimize (speed 3) (safety 2))
    #-swank '(optimize (speed 3) (safety 0) (debug 0)))
  #+swank (progn (ql:quickload '(:cl-debug-print :fiveam))
                 (shadow :run)
                 (use-package :fiveam))
  #-swank (set-dispatch-macro-character #\# #\> (lambda (s c p) (declare (ignore c p)) (read s nil (values) t))))
#+swank (cl-syntax:use-syntax cl-debug-print:debug-print-syntax)

;; BEGIN_INSERTED_CONTENTS
;;
;; Matrix multiplication over semiring
;;

(defun gemm! (a b c &key (op+ #'+) (op* #'*) (identity+ 0))
  "Calculates C := A*B. Destructively modifies C. (OP+, OP*) must form a
semiring. IDENTITY+ is the identity element w.r.t. OP+."
  (declare ((simple-array * (* *)) a b c))
  (dotimes (row (array-dimension a 0))
    (dotimes (col (array-dimension b 1))
      (let ((res identity+))
        (dotimes (k (array-dimension a 1))
          (setf res
                (funcall op+ (funcall op* (aref a row k) (aref b k col)))))
        (setf (aref c row col) res))))
  c)


(declaim (inline gemm))
(defun gemm (a b &key (op+ #'+) (op* #'*) (identity+ 0))
  "Calculates A*B. (OP+, OP*) must form a semiring. IDENTITY+ is the identity
element w.r.t. OP+."
  (declare ((simple-array * (* *)) a b)
           (function op+ op*))
  (let ((c (make-array (list (array-dimension a 0) (array-dimension b 1))
                       :element-type (array-element-type a))))
    (dotimes (row (array-dimension a 0))
      (dotimes (col (array-dimension b 1))
        (let ((res identity+))
          (dotimes (k (array-dimension a 1))
            (setf res
                  (funcall op+ res (funcall op* (aref a row k) (aref b k col)))))
          (setf (aref c row col) res))))
    c))

(declaim (inline matrix-power))
(defun matrix-power (base power &key (op+ #'+) (op* #'*) (identity+ 0) (identity* 1))
  (declare ((simple-array * (* *)) base)
           (function op+ op*)
           ((integer 0 #.most-positive-fixnum) power))
  (let ((size (array-dimension base 0)))
    (assert (= size (array-dimension base 1)))
    (let ((iden (make-array (array-dimensions base)
                            :element-type (array-element-type base)
                            :initial-element identity+)))
      (dotimes (i size)
        (setf (aref iden i i) identity*))
      (labels ((recur (p)
                 (declare ((integer 0 #.most-positive-fixnum) p))
                 (cond ((zerop p) iden)
                       ((evenp p)
                        (let ((res (recur (ash p -1))))
                          (gemm res res :op+ op+ :op* op* :identity+ identity+)))
                       (t
                        (gemm base (recur (- p 1))
                              :op+ op+ :op* op* :identity+ identity+)))))
        (recur power)))))

(declaim (inline gemv))
(defun gemv (a x &key (op+ #'+) (op* #'*) (identity+ 0))
  "Calculates A*x for a matrix A and a vector x. (OP+, OP*) must form a
semiring. IDENTITY+ is the identity element w.r.t. OP+."
  (declare ((simple-array * (* *)) a)
           ((simple-array * (*)) x)
           (function op+ op*))
  (let ((y (make-array (array-dimension a 0) :element-type (array-element-type x))))
    (dotimes (i (length y))
      (let ((res identity+))
        (dotimes (j (length x))
          (setf res
                (funcall op+ res (funcall op* (aref a i j) (aref x j)))))
        (setf (aref y i) res)))
    y))

(declaim (inline power-mod))
(defun power-mod (base power &optional (divisor 1000000007))
  "BASE := integer
POWER, DIVISOR := non-negative fixnum"
  (declare ((integer 0 #.most-positive-fixnum) divisor)
           (integer base))
  (labels ((recur (x p)
             (declare ((integer 0 #.most-positive-fixnum) x p))
             (cond ((zerop p) 1)
                   ((evenp p) (recur (mod (* x x) divisor) (ash p -1)))
                   (t (mod (* x (recur x (- p 1))) divisor)))))
    (declare (ftype (function * (values (integer 0 #.most-positive-fixnum) &optional))
                    recur))
    (recur (mod base divisor) power)))

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

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

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

(defconstant +mod+ 1000000007)

;; Body

(defmacro with-mod-operations (divisor &body body)
  (let ((d (gensym)))
    `(let ((,d ,divisor))
       (labels ((mod+ (x y)
                  (mod (+ x y) ,d))
                (mod* (x y)
                  (mod (* x y) ,d)))
         (declare (inline mod+ mod*))
         ,@body))))

(defun main ()
  (let* ((l (read))
         (a (read))
         (b (read))
         (m (read))
         (boundaries (make-array 19 :element-type 'uint62 :initial-element 0)))
    (declare (uint62 l a b)
             (uint31 m)
             ((simple-array uint62 (*)) boundaries))
    (with-mod-operations m
      (dotimes (d 19)
        (setf (aref boundaries d)
              (max 0 (ceiling (- (expt 10 d) a) b))))
      (dotimes (d 19)
        (when (>= (aref boundaries d) l)
          (setf (aref boundaries d) l)
          (setf boundaries (adjust-array boundaries (+ d 1)))
          (return)))
      (let ((res 0))
        (loop for d from 1 below (length boundaries)
              for length = (- (aref boundaries d) (aref boundaries (- d 1)))
              for vec = (make-array 3 :element-type 'uint32)
              for mat = (make-array (list 3 3) :element-type 'uint32 :initial-element 0)
              do (setf (aref vec 0) 0
                       (aref vec 1) 0
                       (aref vec 2) 1)
                 (setf (aref mat 0 0) (mod (expt 10 d) m)
                       (aref mat 0 1) (mod b m)
                       (aref mat 0 2) (mod+ a (mod* b (aref boundaries (- d 1))))
                       (aref mat 1 1) 1
                       (aref mat 1 2) 1
                       (aref mat 2 2) 1)
                 (setq vec (gemv (matrix-power mat length
                                               :op+ #'mod+
                                               :op* #'mod*)
                                 vec
                                 :op+ #'mod+
                                 :op* #'mod*))
                 (setf res
                       (mod+ (mod* res (power-mod (expt 10 d) length m))
                             (aref vec 0))))
        (println res)))))

#-swank(main)


Measured memory_bytes: 42724