Submission #5218721


Source Code Expand

;; -*- 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 #'car args) ,@body))
         (,name ,@(mapcar #'cadr args))))))

;; (with-memoizing (:hash-table :test #'equal :key #'cons)
;;   (defun ...))
;; (with-memoizing (:array (10 10 * 10) :initial-element -1 :element-type 'fixnum)
;;   (defun foo (a b c d) ...) ; C is ignored.
(declaim (type (integer 0 #.most-positive-fixnum) *recursion-depth*))
(defparameter *recursion-depth* 0)

(defmacro with-memoizing (cache-attribs def-form)
  (let* ((cache-attribs (if (atom cache-attribs) (list cache-attribs) cache-attribs))
         (cache-type (first cache-attribs))
         (dimensions-with-* (when (eql cache-type :array) (second cache-attribs)))
         (dimensions (remove '* dimensions-with-*))
         (rank (length dimensions))
         (rest-attribs (ecase cache-type
                         (:hash-table (cdr cache-attribs))
                         (:array (cddr cache-attribs))))
         (key (prog1 (getf rest-attribs :key) (remf rest-attribs :key)))
         (debug (prog1 (getf rest-attribs :debug) (remf rest-attribs :debug)))
         (cache-form (case cache-type
                       (:hash-table `(make-hash-table ,@rest-attribs))
                       (:array `(make-array (list ,@dimensions) ,@rest-attribs))))
         (initial-element (when (eql cache-type :array)
                            (assert (member :initial-element rest-attribs))
                            (getf rest-attribs :initial-element))))
    (let ((cache (gensym))
          (value (gensym))
	  (present-p (gensym))
          (name-alias (gensym))
	  (args-lst (gensym))
          (indices (loop repeat rank collect (gensym))))
      (labels ((debug (name args obj)
                 (let ((value (gensym)))
                   (if debug
                       `(progn
                          (format t "~A~A: (~A ~{~A~^ ~}) =>~%"
                                  (make-string *recursion-depth*
                                               :element-type 'base-char
                                               :initial-element #\ )
                                  *recursion-depth*
                                  ',name
                                  (list ,@args))
                          (let ((,value (let ((*recursion-depth* (1+ *recursion-depth*)))
                                          ,obj)))
                            (format t "~A~A: (~A ~{~A~^ ~}) => ~A~%"
                                    (make-string *recursion-depth*
                                               :element-type 'base-char
                                               :initial-element #\ )
                                    *recursion-depth*
                                    ',name
                                    (list ,@args)
                                    ,value)
                            ,value))
                       obj)))
               (make-cache-check-form (cache-type name args)
                 (debug name
                        args
                        (case cache-type
                          (:hash-table
                           `(let ((,args-lst (funcall ,(or key #'list) ,@args)))
                              (multiple-value-bind (,value ,present-p)
                                  (gethash ,args-lst ,cache)
                                (if ,present-p
                                    ,value
                                    (setf (gethash ,args-lst ,cache)
                                          (,name-alias ,@args))))))
                          (:array
                           (let ((memoized-args (loop for dimension in dimensions-with-*
                                                      for arg in args
                                                      unless (eql dimension '*)
                                                      collect arg)))
                             (if key
                                 `(multiple-value-bind ,indices
                                      (funcall ,key ,@memoized-args)
                                    (let ((,value (aref ,cache ,@indices)))
                                      (if (eql ,initial-element ,value)
                                          (setf (aref ,cache ,@indices)
                                                (,name-alias ,@args))
                                          ,value)))
                                 `(let ((,value (aref ,cache ,@memoized-args)))
                                    (if (eql ,initial-element ,value)
                                        (setf (aref ,cache ,@memoized-args)
                                              (,name-alias ,@args))
                                        ,value))))))))
               (make-reset-form (cache-type)
                 (case cache-type
                   (:hash-table `(setf ,cache (make-hash-table ,@rest-attribs)))
                   (:array `(prog1 nil
                              (fill (array-storage-vector ,cache) ,initial-element)))))
               (make-reset-name (name)
                 (intern (format nil "RESET-~A" (symbol-name name))))
               (extract-declarations (body)
                 (remove-if-not (lambda (form) (eql 'declare (car form))) body)))
        (ecase (car def-form)
          ((defun)
           (destructuring-bind (_ name args &body body) def-form
             (declare (ignore _))
             `(let ((,cache ,cache-form))
                (defun ,(make-reset-name name) () ,(make-reset-form cache-type))
                (defun ,name ,args
                  ,@(extract-declarations body)
                  (labels ((,name-alias ,args ,@body))
                    (declare (inline ,name-alias))
                    ,(make-cache-check-form cache-type name args))))))
          ((nlet)
           (destructuring-bind (_ name bindings &body body) def-form
             (declare (ignore _))
             `(let ((,cache ,cache-form))
                (nlet ,name ,bindings
                  ,@(extract-declarations body)
                  ,(let ((args (mapcar (lambda (x) (if (atom x) x (car x))) bindings)))
                     `(labels ((,name-alias ,args ,@body))
                        (declare (inline ,name-alias))
                        ,(make-cache-check-form cache-type name args)))))))
          ((labels flet)
           (destructuring-bind (_ definitions &body labels-body) def-form
             (declare (ignore _))
             (destructuring-bind (name args &body body) (car definitions)
               `(let ((,cache ,cache-form))
                  (,(car def-form)
                   ((,(make-reset-name name) () ,(make-reset-form cache-type))
                    (,name ,args
                           ,@(extract-declarations body)
                           (labels ((,name-alias ,args ,@body))
                             (declare (inline ,name-alias))
                             ,(make-cache-check-form cache-type name args)))
                    ,@(cdr definitions))
                   (declare (ignorable #',(make-reset-name name)))
                   ,@labels-body))))))))))

;; (test with-memoizing
;;   (finishes (macroexpand `(with-memoizing (:hash-table :test #'equal)
;;                             (defun add (x y) (+ x y)))))
;;   (finishes (macroexpand `(with-memoizing (:array '(10 10)
;;                                            :element-type 'fixnum
;;                                            :initial-element -1)
;;                             (defun add (x y) (+ x y)))))
;;   (finishes (macroexpand `(with-memoizing (:array '(10 10)
;;                                            :element-type 'fixnum
;;                                            :initial-element -1)
;;                             (labels ((add (x y) (+ x y))
;; 		                     (my-print (x) (print x)))
;; 	                      (add 1 2))))))

;;;
;;; P(n, k) is the number of ways of writing n as a sum of at least k positive
;;; integers.
;;; 
;;; corner cases:
;;; P(0, k) = 1
;;; P(n, 0) = 0 (n ≠ 0)
;;; P(n, k) = P(n, n) (k > n)
;;;

(defconstant +partition-size+ 1100)
(defconstant +partition-mod+ #.(+ (expt 10 9) 7))

(declaim ((simple-array (unsigned-byte 32) (#.+partition-size+ #.+partition-size+)) *partition*))
(defparameter *partition*
  (make-array (list +partition-size+ +partition-size+)
              :element-type '(unsigned-byte 32)
              :initial-element 0))

(defun initialize-partition ()
  "Fills *PARTITION* using P(n, k) = P(n, k-1) + P(n-k, k)."
  (declare #.OPT)
  (dotimes (k +partition-size+)
    (setf (aref *partition* 0 k) 1))
  (loop for n from 1 below +partition-size+
        do (setf (aref *partition* n 0) 0)
           (loop for k from 1 to n
                 do (setf (aref *partition* n k)
                          (mod (+ (aref *partition* n (- k 1))
                                  (aref *partition* (- n k) k))
                               +partition-mod+)))
           (loop for k from (+ n 1) below +partition-size+
                 do (setf (aref *partition* n k)
                          (aref *partition* n n)))))

(initialize-partition)


(declaim (ftype (function * (values fixnum &optional)) read-fixnum))
(defun read-fixnum (&optional (in *standard-input*))
  (declare #.OPT)
  (macrolet ((%read-byte ()
               `(the (unsigned-byte 8)
                     #+swank (char-code (read-char in nil #\Nul))
                     #-swank (sb-impl::ansi-stream-read-byte in nil #.(char-code #\Nul) nil))))
    (let* ((minus nil)
           (result (loop (let ((byte (%read-byte)))
                           (cond ((<= 48 byte 57)
                                  (return (- byte 48)))
                                 ((zerop byte) ; #\Nul
                                  ;; (return-from read-fixnum 0)
                                  (error "Read EOF or #\Nul."))
                                 ((= byte #.(char-code #\-))
                                  (setf minus t)))))))
      (declare ((integer 0 #.most-positive-fixnum) result))
      (loop
        (let* ((byte (%read-byte)))
          (if (<= 48 byte 57)
              (setq result (+ (- byte 48) (the fixnum (* result 10))))
              (return (if minus (- result) result))))))))

(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

(defun solve (team-sizes death-sum)
  (declare #.OPT
           ((simple-array uint16 (*)) team-sizes))
  (with-memoizing (:array (101 1001) :initial-element #xffffffff :element-type 'uint32)
    (nlet recur ((x (length team-sizes)) (y death-sum))
      (if (zerop x)
          (if (zerop y)
              1
              0)
          (loop with res of-type uint31 = 0
                for d from 0 to y
                do (setf res (mod (+ res
                                     (* (recur (- x 1) (- y d))
                                        (aref *partition* d (aref team-sizes (- x 1)))))
                                  +mod+))
                finally (return res))))))

(defun main ()
  (declare #.OPT)
  (let* ((n (read))
         (m (read))
         (as (make-array n :element-type 'uint16))
         (bs (make-array m :element-type 'uint16))
         (a-rle (make-array 0 :element-type 'uint16 :fill-pointer 0))
         (b-rle (make-array 0 :element-type 'uint16 :fill-pointer 0)))
    (dotimes (i n)
      (setf (aref as i) (read-fixnum)))
    (dotimes (i m)
      (setf (aref bs i) (read-fixnum)))
    (let ((base 0))
      (dotimes (i n (vector-push-extend (- i base) a-rle))
        (unless (= (aref as i) (aref as base))
          (vector-push-extend (- i base) a-rle)
          (setf base i))))
    (let ((base 0))
      (dotimes (i m (vector-push-extend (- i base) b-rle))
        (unless (= (aref bs i) (aref bs base))
          (vector-push-extend (- i base) b-rle)
          (setf base i))))
    (setf a-rle (coerce a-rle '(simple-array uint16 (*))))
    (setf b-rle (coerce b-rle '(simple-array uint16 (*))))
    (println (mod (* (solve a-rle (reduce #'+ bs))
                     (solve b-rle (reduce #'+ as)))
                  +mod+))))

#-swank(main)

Submission Info

Submission Time
Task C - Kill/Death
User sansaqua
Language Common Lisp (SBCL 1.1.14)
Score 500
Code Size 13658 Byte
Status AC
Exec Time 393 ms
Memory 43624 KiB

Judge Result

Set Name All
Score / Max Score 500 / 500
Status
AC × 71
Set Name Test Cases
All 01_sample00, 01_sample01, 01_sample02, 01_sample03, 01_sample04, 02_minimal00, 02_minimal01, 02_minimal02, 02_minimal03, 03_maximal00, 03_maximal01, 04_random-easy00, 04_random-easy01, 04_random-easy02, 04_random-easy03, 04_random-easy04, 04_random-easy05, 04_random-easy06, 04_random-easy07, 04_random-easy08, 04_random-easy09, 04_random-easy10, 04_random-easy11, 04_random-easy12, 04_random-easy13, 04_random-easy14, 04_random-easy15, 04_random-easy16, 04_random-easy17, 04_random-easy18, 04_random-easy19, 05_random-large00, 05_random-large01, 05_random-large02, 05_random-large03, 05_random-large04, 05_random-large05, 05_random-large06, 05_random-large07, 05_random-large08, 05_random-large09, 05_random-large10, 05_random-large11, 05_random-large12, 05_random-large13, 05_random-large14, 05_random-large15, 05_random-large16, 05_random-large17, 05_random-large18, 05_random-large19, 06_random00, 06_random01, 06_random02, 06_random03, 06_random04, 06_random05, 06_random06, 06_random07, 06_random08, 06_random09, 06_random10, 06_random11, 06_random12, 06_random13, 06_random14, 06_random15, 06_random16, 06_random17, 06_random18, 06_random19
Case Name Status Exec Time Memory
01_sample00 AC 303 ms 43624 KiB
01_sample01 AC 139 ms 31204 KiB
01_sample02 AC 142 ms 31208 KiB
01_sample03 AC 141 ms 31200 KiB
01_sample04 AC 139 ms 31200 KiB
02_minimal00 AC 133 ms 31208 KiB
02_minimal01 AC 134 ms 31204 KiB
02_minimal02 AC 133 ms 31200 KiB
02_minimal03 AC 134 ms 31204 KiB
03_maximal00 AC 142 ms 31204 KiB
03_maximal01 AC 134 ms 31200 KiB
04_random-easy00 AC 133 ms 31204 KiB
04_random-easy01 AC 133 ms 31200 KiB
04_random-easy02 AC 133 ms 31204 KiB
04_random-easy03 AC 133 ms 31200 KiB
04_random-easy04 AC 134 ms 31204 KiB
04_random-easy05 AC 133 ms 31208 KiB
04_random-easy06 AC 133 ms 31204 KiB
04_random-easy07 AC 133 ms 31204 KiB
04_random-easy08 AC 133 ms 31200 KiB
04_random-easy09 AC 133 ms 31200 KiB
04_random-easy10 AC 133 ms 31204 KiB
04_random-easy11 AC 133 ms 31200 KiB
04_random-easy12 AC 134 ms 31204 KiB
04_random-easy13 AC 134 ms 31200 KiB
04_random-easy14 AC 135 ms 31200 KiB
04_random-easy15 AC 137 ms 31204 KiB
04_random-easy16 AC 135 ms 31204 KiB
04_random-easy17 AC 138 ms 31208 KiB
04_random-easy18 AC 136 ms 31204 KiB
04_random-easy19 AC 135 ms 31204 KiB
05_random-large00 AC 347 ms 31204 KiB
05_random-large01 AC 393 ms 31204 KiB
05_random-large02 AC 369 ms 31204 KiB
05_random-large03 AC 350 ms 31200 KiB
05_random-large04 AC 357 ms 31208 KiB
05_random-large05 AC 374 ms 31204 KiB
05_random-large06 AC 371 ms 31200 KiB
05_random-large07 AC 366 ms 31204 KiB
05_random-large08 AC 355 ms 31204 KiB
05_random-large09 AC 349 ms 31208 KiB
05_random-large10 AC 355 ms 31204 KiB
05_random-large11 AC 358 ms 31204 KiB
05_random-large12 AC 366 ms 31208 KiB
05_random-large13 AC 373 ms 31200 KiB
05_random-large14 AC 366 ms 31200 KiB
05_random-large15 AC 332 ms 31200 KiB
05_random-large16 AC 363 ms 31200 KiB
05_random-large17 AC 375 ms 31204 KiB
05_random-large18 AC 367 ms 31208 KiB
05_random-large19 AC 351 ms 31204 KiB
06_random00 AC 244 ms 31204 KiB
06_random01 AC 135 ms 31208 KiB
06_random02 AC 137 ms 31200 KiB
06_random03 AC 262 ms 31204 KiB
06_random04 AC 181 ms 31204 KiB
06_random05 AC 195 ms 31208 KiB
06_random06 AC 156 ms 31200 KiB
06_random07 AC 175 ms 31204 KiB
06_random08 AC 153 ms 31204 KiB
06_random09 AC 260 ms 31208 KiB
06_random10 AC 144 ms 31208 KiB
06_random11 AC 167 ms 31204 KiB
06_random12 AC 263 ms 31200 KiB
06_random13 AC 166 ms 31200 KiB
06_random14 AC 170 ms 31200 KiB
06_random15 AC 134 ms 31204 KiB
06_random16 AC 200 ms 31204 KiB
06_random17 AC 174 ms 31204 KiB
06_random18 AC 153 ms 31204 KiB
06_random19 AC 157 ms 31204 KiB