提出 #6320820
ソースコード 拡げる
;; -*- 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
;;;
;;; Extended Eratosthenes' sieve (osa_k's method)
;;;
;;; build: O(n)
;;; With this sieve each prime factorization can be executed in O(log(n)), which
;;; is faster than the well known one in O(N/log(n) + log(n)).
;;; Reference: http://www.osak.jp/diary/diary_201310.html#20131017
;;;
(defun make-minfactor-table (sup)
"Returns a vector of length SUP, whose (0-based) i-th value is the minimal
prime factor of i. (Corner case: 0th value is 0 and 1st value is 1.)"
(declare #.OPT)
(check-type sup (integer 2 (#.array-total-size-limit)))
(let ((table (make-array sup :element-type '(unsigned-byte 32))))
;; initialize
(dotimes (i sup) (setf (aref table i) i))
;; p = 2
(loop for even-num from 4 below sup by 2
do (setf (aref table even-num) 2))
;; p >= 3
(loop for p from 3 to (+ 1 (isqrt (- sup 1))) by 2
when (= p (aref table p))
do (loop for composite from (* p p) below sup by p
when (= (aref table composite) composite)
do (setf (aref table composite) p)))
table))
(defun factorize (x minfactor-table)
"Returns the associative list of prime factors of X, which is composed
of (<prime> . <exponent>). E.g. (factorize 100 <minfactor-table>) => '((2
. 2) (5 . 5)). The returned list is in ascending order
w.r.t. prime. Note: (FACTORIZE 0 TABLE) |-> NIL.
MINFACTOR-TABLE := vector (MINFACTOR-TABLE[k] is the minimal prime factor of k)"
(declare #.OPT
(fixnum x)
((simple-array (unsigned-byte 32) (*)) minfactor-table))
(setq x (abs x))
(when (<= x 1) (return-from factorize nil))
(assert (< x (length minfactor-table)))
(loop until (= x 1)
for prime of-type (integer 0 #.most-positive-fixnum) = (aref minfactor-table x)
collect (loop for exponent of-type (integer 0 #.most-positive-fixnum) from 0
do (multiple-value-bind (quot rem) (floor x prime)
(if (zerop rem)
(setf x quot)
(loop-finish)))
finally (return (cons prime exponent)))))
(defconstant +binom-size+ 1600000)
(defconstant +binom-mod+ #.(+ (expt 10 9) 7))
(declaim ((simple-array (unsigned-byte 32) (*)) *inv*))
(defparameter *inv* (make-array +binom-size+ :element-type '(unsigned-byte 32)))
(defun initialize-binom ()
(declare #.OPT)
(setf (aref *inv* 1) 1)
(loop for i from 2 below +binom-size+
do (setf (aref *inv* i)
(- +binom-mod+
(rem (* (aref *inv* (rem +binom-mod+ i))
(floor +binom-mod+ i))
+binom-mod+)))))
(initialize-binom)
(defmacro with-output-buffer (&body body)
"Buffers all outputs to *STANDARD-OUTPUT* in BODY and flushes them to
*STANDARD-OUTPUT* after BODY has been done (without error). Note that only
BASE-CHAR is allowed."
(let ((out (gensym)))
`(let ((,out (make-string-output-stream :element-type 'base-char)))
(let ((*standard-output* ,out))
,@body)
(write-string (get-output-stream-string ,out)))))
(declaim (ftype (function * (values fixnum &optional)) read-fixnum+))
(defun read-fixnum+ (&optional (in *standard-input*))
(declare #.OPT
#-swank (sb-kernel:ansi-stream in))
(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* ((result (loop (let ((byte (%read-byte)))
(cond ((<= 48 byte 57)
(return (- byte 48)))
((zerop byte) ; #\Nul
(error "Read EOF or #\Nul.")))))))
(declare ((integer 0 #.most-positive-fixnum) result))
(loop
(let* ((byte (%read-byte)))
(if (<= 48 byte 57)
(setq result (+ (- byte 48) (* 10 (the (integer 0 #.(floor most-positive-fixnum 10)) result))))
(return result)))))))
(defstruct (mo (:constructor %make-mo
(lefts rights order width))
(:conc-name %mo-)
(:copier nil)
(:predicate nil))
(lefts nil :type (simple-array (unsigned-byte 32) (*)))
(rights nil :type (simple-array (unsigned-byte 32) (*)))
(order nil :type (simple-array (unsigned-byte 32) (*)))
(width 0 :type (integer 0 #.most-positive-fixnum))
(index 0 :type (integer 0 #.most-positive-fixnum))
(posl 0 :type fixnum)
(posr 0 :type fixnum)
(old-posl 0 :type fixnum)
(old-posr 0 :type fixnum))
(defun make-mo (total-width lefts rights)
"TOTAL-WIDTH is the width of the interval on which the queries exist. (NOT the
number of queries.)"
(declare #.OPT
((simple-array (unsigned-byte 32) (*)) lefts rights)
((integer 0 #.most-positive-fixnum) total-width)
(inline sort))
(let* ((q (length lefts))
(order (make-array q :element-type '(unsigned-byte 32)))
(width (floor total-width (isqrt q))))
(declare ((integer 0 #.most-positive-fixnum) width))
(assert (= q (length rights)))
(dotimes (i q) (setf (aref order i) i))
(setf order (sort order
(lambda (x y)
(if (= (floor (aref lefts x) width)
(floor (aref lefts y) width))
;; Even-number [Odd-number] block is in ascending
;; [descending] order w.r.t. the right boundary.
(if (evenp (floor (aref lefts x) width))
(< (aref rights x) (aref rights y))
(> (aref rights x) (aref rights y)))
(< (aref lefts x) (aref lefts y))))))
(%make-mo lefts rights order width)))
(declaim (inline mo-get-current))
(defun mo-get-current (mo)
"Returns the original index of the current query."
(aref (%mo-order mo) (%mo-index mo)))
(declaim (inline mo-process))
(defun mo-process (mo extend shrink)
"Processes the next query."
(declare (function extend shrink))
(let* ((ord (mo-get-current mo))
(left (aref (%mo-lefts mo) ord))
(right (aref (%mo-rights mo) ord))
(posl (%mo-posl mo))
(posr (%mo-posr mo)))
(declare ((integer 0 #.most-positive-fixnum) posl posr))
(setf (%mo-old-posl mo) posl
(%mo-old-posr mo) posr)
(loop while (< left posl)
do (decf posl)
(funcall extend posl))
(loop while (< posr right)
do (funcall extend posr)
(incf posr))
(loop while (< posl left)
do (funcall shrink posl)
(incf posl))
(loop while (< right posr)
do (decf posr)
(funcall shrink posr))
(setf (%mo-posl mo) posl
(%mo-posr mo) posr)
(incf (%mo-index mo))))
(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
;; TODO: Is it better to use DEFTRANSFORM to optimize these functions when they
;; are passed to an inlined function?
;; TODO: define WITH-MOD-OPERATIONS to make them dynamic (though we cannot add
;; compiler-macro nor transformer in this case...)
(defmacro define-mod-operations (&optional (divisor 1000000007))
`(progn
(defun mod* (&rest args)
(reduce (lambda (x y) (mod (* x y) ,divisor)) args))
(define-compiler-macro 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))
(define-compiler-macro mod+ (&rest args)
(if (null args)
0
(reduce (lambda (x y) `(mod (+ ,x ,y) ,',divisor)) args)))
(define-modify-macro incfmod (delta divisor)
(lambda (x y divisor) (mod (+ x y) divisor)))
(define-modify-macro decfmod (delta divisor)
(lambda (x y divisor) (mod (- x y) divisor)))))
(define-mod-operations)
(defun main ()
(declare #.OPT)
(let* ((n (read))
(q (read))
(minfactors (make-minfactor-table 100001))
(xs (make-array n :element-type 'list :initial-element nil))
(ls (make-array q :element-type 'uint32))
(rs (make-array q :element-type 'uint32))
(res (make-array q :element-type 'uint32)))
(declare (uint32 n)
((simple-array uint32 (*)) minfactors))
(dotimes (i n)
(setf (aref xs i) (factorize (read-fixnum+) minfactors)))
(dotimes (i q)
(setf (aref ls i) (- (read-fixnum+) 1))
(setf (aref rs i) (read-fixnum+)))
(let ((value 1)
(table (make-array 100001 :element-type 'uint32 :initial-element 1))
(mo (make-mo n ls rs)))
(declare (uint32 value))
(dotimes (_ q)
(let ((pos (mo-get-current mo)))
(mo-process mo
(lambda (idx)
(let ((factors (aref xs idx)))
(dolist (node factors)
(let* ((prime (car node))
(delta (cdr node))
(old-count (aref table prime))
(new-count (+ old-count delta)))
(declare (uint32 prime delta old-count new-count))
(setq value (mod* value new-count (aref *inv* old-count)))
(setf (aref table prime) new-count)))))
(lambda (idx)
(let ((factors (aref xs idx)))
(dolist (node factors)
(let* ((prime (car node))
(delta (cdr node))
(old-count (aref table prime))
(new-count (- old-count delta)))
(declare (uint32 prime delta old-count new-count))
(setq value (mod* value new-count (aref *inv* old-count)))
(setf (aref table prime) new-count))))))
(setf (aref res pos) value)))
(with-output-buffer (dotimes (i q) (println (aref res i)))))))
#-swank(main)
提出情報
| 提出日時 |
|
| 問題 |
B - ニワンゴくんの約数 |
| ユーザ |
sansaqua |
| 言語 |
Common Lisp (SBCL 1.1.14) |
| 得点 |
1100 |
| コード長 |
11806 Byte |
| 結果 |
AC |
| 実行時間 |
2334 ms |
| メモリ |
84708 KiB |
ジャッジ結果
| セット名 |
Sample |
All |
| 得点 / 配点 |
0 / 0 |
1100 / 1100 |
| 結果 |
|
|
| セット名 |
テストケース |
| Sample |
s1.txt, s2.txt |
| All |
01.txt, 02.txt, 03.txt, 04.txt, 05.txt, 06.txt, 07.txt, 08.txt, 09.txt, 10.txt, 11.txt, 12.txt, 13.txt, 14.txt, 15.txt, 16.txt, 17.txt, 18.txt, 19.txt, 20.txt, 21.txt, 22.txt, s1.txt, s2.txt |
| ケース名 |
結果 |
実行時間 |
メモリ |
| 01.txt |
AC |
976 ms |
84708 KiB |
| 02.txt |
AC |
1351 ms |
71400 KiB |
| 03.txt |
AC |
721 ms |
63204 KiB |
| 04.txt |
AC |
1119 ms |
65248 KiB |
| 05.txt |
AC |
982 ms |
69352 KiB |
| 06.txt |
AC |
1748 ms |
69352 KiB |
| 07.txt |
AC |
890 ms |
69348 KiB |
| 08.txt |
AC |
1494 ms |
69348 KiB |
| 09.txt |
AC |
753 ms |
71392 KiB |
| 10.txt |
AC |
1324 ms |
71396 KiB |
| 11.txt |
AC |
733 ms |
65248 KiB |
| 12.txt |
AC |
1104 ms |
63204 KiB |
| 13.txt |
AC |
580 ms |
58720 KiB |
| 14.txt |
AC |
764 ms |
58728 KiB |
| 15.txt |
AC |
602 ms |
58852 KiB |
| 16.txt |
AC |
788 ms |
58724 KiB |
| 17.txt |
AC |
1212 ms |
71392 KiB |
| 18.txt |
AC |
2334 ms |
71392 KiB |
| 19.txt |
AC |
993 ms |
69224 KiB |
| 20.txt |
AC |
1756 ms |
69352 KiB |
| 21.txt |
AC |
664 ms |
63200 KiB |
| 22.txt |
AC |
956 ms |
63208 KiB |
| s1.txt |
AC |
256 ms |
45796 KiB |
| s2.txt |
AC |
258 ms |
45792 KiB |