提出 #6773956
ソースコード 拡げる
;; -*- 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 (ql:quickload '(:cl-debug-print :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)
#-swank (disable-debugger) ; for CS Academy
;; BEGIN_INSERTED_CONTENTS
(defconstant +mod+ 1000000007)
;;;
;;; Binomial coefficient with mod
;;; build: O(n)
;;; query: O(1)
;;;
(defconstant +binom-size+ 1001)
(defconstant +binom-mod+ +mod+)
(declaim ((simple-array (unsigned-byte 32) (*)) *fact* *fact-inv* *inv*))
(defparameter *fact* (make-array +binom-size+ :element-type '(unsigned-byte 32)))
(defparameter *fact-inv* (make-array +binom-size+ :element-type '(unsigned-byte 32)))
(defparameter *inv* (make-array +binom-size+ :element-type '(unsigned-byte 32)))
(defun initialize-binom ()
(declare (optimize (speed 3) (safety 0)))
(setf (aref *fact* 0) 1
(aref *fact* 1) 1
(aref *fact-inv* 0) 1
(aref *fact-inv* 1) 1
(aref *inv* 1) 1)
(loop for i from 2 below +binom-size+
do (setf (aref *fact* i) (mod (* i (aref *fact* (- i 1))) +binom-mod+)
(aref *inv* i) (- +binom-mod+
(mod (* (aref *inv* (rem +binom-mod+ i))
(floor +binom-mod+ i))
+binom-mod+))
(aref *fact-inv* i) (mod (* (aref *inv* i)
(aref *fact-inv* (- i 1)))
+binom-mod+))))
(initialize-binom)
;;;
;;; Memoization macro
;;;
;;
;; Basic usage:
;; (with-cache (:hash-table :test #'equal :key #'cons)
;; (defun add (a b)
;; (+ a b)))
;; This function caches the returned values for already passed combinations of
;; arguments. In this case ADD stores the key (CONS A B) and the corresponding
;; value to a hash-table when evaluating (ADD A B) for the first time; ADD
;; returns the stored value when it is called with the same arguments
;; (w.r.t. EQUAL) again.
;;
;; The storage for the cache can be hash-table or array. Let's see an example
;; for array:
;; (with-cache (:array (10 20 30) :initial-element -1 :element-type 'fixnum)
;; (defun foo (a b c) ... ))
;; This form caches the value of FOO in the array created by (make-array (list
;; 10 20 30) :initial-element -1 :element-type 'fixnum). Note that
;; INITIAL-ELEMENT must always be given here as it is used as the flag for `not
;; yet stored'. (Therefore INITIAL-ELEMENT should be a value FOO doesn't take.)
;;
;; If you want to ignore some arguments, you can use `*' in dimensions:
;; (with-cache (:array (10 10 * 10) :initial-element -1)
;; (defun foo (a b c d) ...)) ; => C is ignored when querying or storing cache
;;
;; Available definition forms in WITH-CACHE are DEFUN, LABELS, FLET, and
;; SB-INT:NAMED-LET.
;;
;; You can debug the memoized function by :DEBUG option:
;; (with-cache (:array (10 10) :initial-element -1 :debug t)
;; (defun foo (x y) ...))
;; Then FOO is traced as with CL:TRACE.
;;
;; FIXME: *RECURSION-DEPTH* should be included within the macro.
(declaim (type (integer 0 #.most-positive-fixnum) *recursion-depth*))
(defparameter *recursion-depth* 0)
(defmacro with-cache ((cache-type &rest cache-attribs) def-form)
"CACHE-TYPE := :HASH-TABLE | :ARRAY"
(assert (member cache-type '(:hash-table :array)))
(let* ((dimensions-with-* (when (eql cache-type :array) (first cache-attribs)))
(dimensions (remove '* dimensions-with-*))
(rank (length dimensions))
(rest-attribs (ecase cache-type
(:hash-table cache-attribs)
(:array (cdr 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 "CACHE"))
(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 #+sbcl sb-int:named-let)
(destructuring-bind (_ name bindings &body body) def-form
(declare (ignore _))
`(let ((,cache ,cache-form))
(,(car def-form) ,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))))))))))
(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))))
;; Body
;;;
;;; Arithmetic operations with static modulus
;;;
(defmacro define-mod-operations (&optional (divisor 1000000007))
`(progn
(defun mod* (&rest args)
(reduce (lambda (x y) (mod (* x y) ,divisor)) args))
(sb-c:define-source-transform mod* (&rest args)
(if (null args)
1
(reduce (lambda (x y) `(mod (* ,x ,y) ,',divisor)) args)))
(defun mod+ (&rest args)
(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 mulfmod (delta)
(lambda (x y) (mod (* x y) ,divisor)))
(define-modify-macro decfmod (delta)
(lambda (x y) (mod (- x y) ,divisor)))))
(define-mod-operations +mod+)
(defun main ()
(declare #.OPT)
(let* ((n (read))
(a (read))
(b (read))
(c (read))
(d (read)))
(declare (uint16 n a b c d))
(println
(with-cache (:array (1001 1001) :initial-element #xffffffff :element-type 'uint32)
(sb-int:named-let recur ((x n) (y b))
(declare (uint16 x y))
(cond ((zerop x) 1)
((< y a) 0)
(t
(let ((res (recur x (- y 1)))
(factor (aref *fact* x)))
(declare (uint32 res factor))
(loop for i from 0 below (- c 1)
while (<= (* i y) x)
do (mulfmod factor (aref *fact-inv* y)))
(loop for k from c to d
while (<= (* k y) x)
do (mulfmod factor (aref *fact-inv* y))
(incfmod res
(mod* (recur (- x (* k y)) (- y 1))
factor
(aref *fact-inv* (- x (* k y)))
(aref *fact-inv* k))))
res))))))))
#-swank (main)
提出情報
| 提出日時 |
|
| 問題 |
E - Grouping |
| ユーザ |
sansaqua |
| 言語 |
Common Lisp (SBCL 1.1.14) |
| 得点 |
600 |
| コード長 |
13331 Byte |
| 結果 |
AC |
| 実行時間 |
303 ms |
| メモリ |
43236 KiB |
ジャッジ結果
| セット名 |
Sample |
All |
| 得点 / 配点 |
0 / 0 |
600 / 600 |
| 結果 |
|
|
| セット名 |
テストケース |
| Sample |
sample_01.txt, sample_02.txt, sample_03.txt, sample_04.txt |
| All |
sample_01.txt, sample_02.txt, sample_03.txt, sample_04.txt, subtask_1_many_01.txt, subtask_1_many_02.txt, subtask_1_many_03.txt, subtask_1_many_04.txt, subtask_1_max_01.txt, subtask_1_max_02.txt, subtask_1_min_01.txt, subtask_1_randa_01.txt, subtask_1_randa_02.txt, subtask_1_randb_01.txt, subtask_1_randb_02.txt |
| ケース名 |
結果 |
実行時間 |
メモリ |
| sample_01.txt |
AC |
303 ms |
43236 KiB |
| sample_02.txt |
AC |
134 ms |
31204 KiB |
| sample_03.txt |
AC |
198 ms |
31204 KiB |
| sample_04.txt |
AC |
133 ms |
31204 KiB |
| subtask_1_many_01.txt |
AC |
181 ms |
31204 KiB |
| subtask_1_many_02.txt |
AC |
166 ms |
31204 KiB |
| subtask_1_many_03.txt |
AC |
179 ms |
31204 KiB |
| subtask_1_many_04.txt |
AC |
176 ms |
31200 KiB |
| subtask_1_max_01.txt |
AC |
136 ms |
31204 KiB |
| subtask_1_max_02.txt |
AC |
138 ms |
31204 KiB |
| subtask_1_min_01.txt |
AC |
136 ms |
31208 KiB |
| subtask_1_randa_01.txt |
AC |
135 ms |
31208 KiB |
| subtask_1_randa_02.txt |
AC |
134 ms |
31208 KiB |
| subtask_1_randb_01.txt |
AC |
135 ms |
31208 KiB |
| subtask_1_randb_02.txt |
AC |
135 ms |
31204 KiB |