;; -*- 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 (cl-syntax:use-syntax cl-debug-print:debug-print-syntax)

;; BEGIN_INSERTED_CONTENTS
(defmacro nlet (name args &body body)
  (labels ((ensure-list (x) (if (listp x) x (list x))))
    (let ((args (mapcar #'ensure-list args)))
      `(labels ((,name ,(mapcar #'first args) ,@body))
         (,name ,@(mapcar #'second args))))))

(declaim (ftype (function * (values simple-bit-vector &optional)) make-prime-table))
(defun make-prime-table (size)
  "Erzeugt die Primzahlentabelle 0 zu SIZE-1."
  (declare #.OPT)
  (let ((dict (make-array size :element-type 'bit :initial-element 1)))
    (setf (sbit dict 0) 0 (sbit dict 1) 0)
    (loop for even-num from 4 below size by 2
          do (setf (sbit dict even-num) 0))
    (loop for p from 3 to (ceiling (sqrt size)) by 2
          when (= 1 (sbit dict p))
          do (loop for composite from (+ p p) below size by p
                   until (>= composite size)
                   do (setf (sbit dict composite) 0)))
    dict))

(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 4 7 8 15 16 31 32 62 63 64)

(defmacro println (obj &optional (stream '*standard-output*))
  `(let ((*read-default-float-format* 'double-float))
     (prog1 (princ ,obj ,stream) (terpri ,stream))))

;; Hauptteil
(defconstant +magic+ #.(+ 7 (expt 10 9)))
(defun decompose (m)
  (declare #.OPT
           (uint32 m))
  (let* ((factor-sup (ceiling (sqrt m)))
         (prime-table (make-prime-table (1+ factor-sup))))
    (loop for i from 2 below (length prime-table)
          when (= 1 (sbit prime-table i))
          collect (nlet recurse ((count 0))
                    (declare (uint32 count))
                    (multiple-value-bind (quot rem) (floor m i)
                      (if (zerop rem)
                          (progn (setf m quot)
                                 (recurse (1+ count)))
                          count)))
          into factors
          finally (return
                    (let ((factors (delete 0 (the list factors))))
                      (if (= 1 m)
                          factors
                          (append factors (list 1))))))))

;; Based on alexandria
;; (declaim (inline %multiply-range))
(defun %multiply-range (i j)
  (labels ((bisect (j k)
             (declare (type (integer 1 #.most-positive-fixnum) j k)
                      (values integer))
             (if (< (- k j) 8)
                 (multiply-range j k)
                 (let ((middle (+ j (truncate (- k j) 2))))
                   (* (bisect j middle)
                      (bisect (+ middle 1) k)))))
           (multiply-range (j k)
             (declare (type (integer 1 #.most-positive-fixnum) j k))
             (do ((f k (* f m))
                  (m (1- k) (1- m)))
                 ((< m j) f)
               (declare (type (integer 0 (#.most-positive-fixnum)) m)
                        (type unsigned-byte f)))))
    (bisect i j)))

(defun binomial-coefficient (n k)
  (declare ((integer 0 (#.most-positive-fixnum)) n k))
  (assert (>= n k))
  (mod (if (or (zerop k) (= n k))
           1
           (let ((n-k (- n k)))
             (when (< k n-k)
               (rotatef k n-k))
             (if (= 1 n-k)
                 n
                 (floor (%multiply-range (+ k 1) n)
	                (%multiply-range 1 n-k)))))
       +magic+))

(defun multiset-coefficient (n k)
  (binomial-coefficient (+ n k -1) k))

(defun main ()
  (let* ((n (read))
         (m (read))
         (factors (decompose m)))
    (if (= m 1)
        (println 1)
        (println
         (reduce (lambda (x y) (mod (* x y) +magic+))
                 factors
                 :key (lambda (k) (multiset-coefficient n k)))))))

#-swank(main)


Measured memory_bytes: 26976