提出 #9890003
ソースコード 拡げる
(eval-when (:compile-toplevel :load-toplevel :execute) (sb-int:defconstant-eqx OPT #+swank '(optimize (speed 3) (safety 2)) #-swank '(optimize (speed 3) (safety 0) (debug 0)) #'equal) #+swank (ql:quickload '(:cl-debug-print :fiveam) :silent t) #-swank (set-dispatch-macro-character ;; enclose the form with VALUES to avoid being captured by LOOP macro #\# #\> (lambda (s c p) (declare (ignore c p)) `(values ,(read s nil nil t))))) #+swank (cl-syntax:use-syntax cl-debug-print:debug-print-syntax) #-swank (disable-debugger) ; for CS Academy ;; BEGIN_INSERTED_CONTENTS (declaim (ftype (function * (values fixnum &optional)) read-fixnum)) (defun read-fixnum (&optional (in *standard-input*)) "NOTE: cannot read -2^62" (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 (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) (* 10 (the (integer 0 #.(floor most-positive-fixnum 10)) result)))) (return (if minus (- result) result)))))))) ;;; ;;; Calculate a^n on any monoids in O(log(n)) time ;;; ;; (declaim (inline power)) ;; (defun power (base exponent op identity) ;; "OP := binary operation (comprising a monoid) ;; IDENTITY := identity element w.r.t. OP" ;; (declare ((integer 0) exponent)) ;; (labels ((recur (x p) ;; (declare ((integer 0 #.most-positive-fixnum) p)) ;; (cond ((zerop p) identity) ;; ((evenp p) (recur (funcall op x x) (ash p -1))) ;; (t (nth-value 0 (funcall op x (recur x (- p 1))))))) ;; (recur-big (x p) ;; (declare ((integer 0) p)) ;; (cond ((zerop p) identity) ;; ((evenp p) (recur-big (funcall op x x) (ash p -1))) ;; (t (nth-value 0 (funcall op x (recur-big x (- p 1)))))))) ;; (typecase exponent ;; (fixnum (recur base exponent)) ;; (otherwise (recur-big base exponent))))) (declaim (inline decompose-to-cycles)) (defun decompose-to-cycles (permutation) "Returns the list of all the cyclic permutations in a given permutation of {0, 1, ..., N-1}" (declare (vector permutation)) (let* ((n (length permutation)) result (visited (make-array n :element-type 'bit :initial-element 0))) (dotimes (init n) (when (zerop (sbit visited init)) (push (loop for x = init then (aref permutation x) until (= (sbit visited x) 1) collect x do (setf (sbit visited x) 1)) 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 perm* (perm1 perm2) ;; (let* ((n (length perm1)) ;; (res (make-array n :element-type 'uint31))) ;; (dotimes (i n) ;; (setf (aref res i) (aref perm2 (aref perm1 i)))) ;; res)) ;; (defun perm-power (perm exp) ;; (let ((iden (make-array (length perm) :element-type 'uint31))) ;; (dotimes (i (length perm)) ;; (setf (aref iden i) i)) ;; (power perm exp #'perm* iden))) (declaim (inline lastcar)) (defun lastcar (list) (car (last list))) (defun main () (let* ((n (read)) (k (read)) (as (make-array n :element-type 'uint31)) (res (make-array n :element-type 'uint31))) (declare (uint16 n k)) (dotimes (i n) (setf (aref as i) (- (read-fixnum) 1))) (let ((cycles (decompose-to-cycles as)) (cycle-table (make-array (+ n 1) :element-type 'list :initial-element nil)) (num-table (make-array (+ n 1) :element-type 'uint31 :initial-element 0))) (dolist (cycle cycles) (let ((len (length (the list cycle)))) (incf (aref num-table len)) (push cycle (aref cycle-table len)))) (labels ((no () (println 0) (return-from main)) (render-cycle (len num) (let* ((total (* len num)) (large-perm (make-array total :element-type 'uint31))) (dbg len num total) #>large-perm (let ((index 0)) (declare (uint31 index)) (dotimes (_ num) (let ((cycle (pop (aref cycle-table len)))) #>cycle (dotimes (_ len) (let ((v (pop cycle))) (setf (aref large-perm index) v) (setq index (mod (+ index k) total)))) (setq index (mod (+ index 1) total))))) #>large-perm (dotimes (i (- total 1)) (setf (aref res (aref large-perm i)) (aref large-perm (+ i 1)))) (setf (aref res (aref large-perm (- total 1))) (aref large-perm 0)) #>res))) (loop for l from 1 to n for l-num = (aref num-table l) for perimtr-set = (make-array 0 :fill-pointer 0 :element-type 'uint31) unless (zerop l-num) do (loop for length from 1 to (* l l-num) when (= length (* (gcd length k) l)) do (vector-push-extend length perimtr-set)) ;; perimtr-setの中の周長Lを使うとgcd(L, k)個の巡回置換が消費で ;; きる。重複を許して自由にこれらの長さを使ってl-num個の巡回置 ;; 換をちょうど消費したい(重複あり部分和問題) (let* ((set-size (length perimtr-set)) (dp (make-array (list (+ 1 set-size) (+ l-num 1)) :element-type 'bit :initial-element 0))) (setf (aref dp 0 0) 1) (loop for x from 1 to set-size for perimeter = (aref perimtr-set (- x 1)) for consum = (gcd perimeter k) do (loop for y from 0 to l-num do (setf (aref dp x y) (logior (if (< y consum) 0 (aref dp x (- y consum))) (aref dp (- x 1) y))))) (when (zerop (aref dp set-size l-num)) (no)) (sb-int:named-let recur ((x set-size) (y l-num)) (declare (uint31 x y)) (unless (and (zerop x) (zerop y)) (if (and (> x 0) (= 1 (aref dp (- x 1) y))) (recur (- x 1) y) (let* ((perimeter (aref perimtr-set (- x 1))) (consum (gcd perimeter k))) (declare (uint31 perimeter consum)) (assert (= 1 (aref dp x (- y consum)))) (render-cycle l consum) (recur x (- y consum)))))))))) (loop for x across res do (println (+ x 1))))) #-swank (main) ;;; ;;; Test and benchmark ;;; #+swank (defun io-equal (in-string out-string &key (function #'main) (test #'equal)) "Passes IN-STRING to *STANDARD-INPUT*, executes FUNCTION, and returns true if the string output to *STANDARD-OUTPUT* is equal to OUT-STRING." (labels ((ensure-last-lf (s) (if (eql (uiop:last-char s) #\Linefeed) s (uiop:strcat s uiop:+lf+)))) (funcall test (ensure-last-lf out-string) (with-output-to-string (out) (let ((*standard-output* out)) (with-input-from-string (*standard-input* (ensure-last-lf in-string)) (funcall function))))))) #+swank (defun get-clipbrd () (with-output-to-string (out) (run-program "powershell.exe" '("-Command" "Get-Clipboard") :output out :search t))) #+swank (defparameter *this-pathname* (uiop:current-lisp-file-pathname)) #+swank (defparameter *dat-pathname* (uiop:merge-pathnames* "test.dat" *this-pathname*)) #+swank (defun run (&optional thing (out *standard-output*)) "THING := null | string | symbol | pathname null: run #'MAIN using the text on clipboard as input. string: run #'MAIN using the string as input. symbol: alias of FIVEAM:RUN!. pathname: run #'MAIN using the text file as input." (let ((*standard-output* out)) (etypecase thing (null (with-input-from-string (*standard-input* (delete #\Return (get-clipbrd))) (main))) (string (with-input-from-string (*standard-input* (delete #\Return thing)) (main))) (symbol (5am:run! thing)) (pathname (with-open-file (*standard-input* thing) (main)))))) #+swank (defun gen-dat () (uiop:with-output-file (out *dat-pathname* :if-exists :supersede) (format out ""))) #+swank (defun bench (&optional (out (make-broadcast-stream))) (time (run *dat-pathname* out))) ;; To run: (5am:run! :sample) #+swank (it.bese.fiveam:test :sample (5am:is (io-equal "3 5 3 1 2 " "2 3 1 ")) (5am:is (io-eqaul "4 4 2 1 4 3 " "0 ")))
提出情報
提出日時 | |
---|---|
問題 | circuit - 電気回路の結線 (Circuit) |
ユーザ | sansaqua |
言語 | Common Lisp (SBCL 1.1.14) |
得点 | 100 |
コード長 | 11129 Byte |
結果 | AC |
実行時間 | 530 ms |
メモリ | 35044 KiB |
ジャッジ結果
セット名 | Set01 | Set02 | Set03 | Set04 | Set05 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
得点 / 配点 | 20 / 20 | 20 / 20 | 20 / 20 | 20 / 20 | 20 / 20 | ||||||||||
結果 |
|
|
|
|
|
セット名 | テストケース |
---|---|
Set01 | 01 |
Set02 | 02 |
Set03 | 03 |
Set04 | 04 |
Set05 | 05 |
ケース名 | 結果 | 実行時間 | メモリ |
---|---|---|---|
01 | AC | 530 ms | 35044 KiB |
02 | AC | 161 ms | 25056 KiB |
03 | AC | 117 ms | 23012 KiB |
04 | AC | 160 ms | 25056 KiB |
05 | AC | 161 ms | 25060 KiB |