結果

問題 No.882 約数倍数
ユーザー sansaquasansaqua
提出日時 2019-09-13 21:21:52
言語 Common Lisp
(sbcl 2.3.8)
結果
AC  
実行時間 9 ms / 500 ms
コード長 6,523 bytes
コンパイル時間 1,075 ms
コンパイル使用メモリ 38,100 KB
実行使用メモリ 29,300 KB
最終ジャッジ日時 2023-09-17 06:52:52
合計ジャッジ時間 1,907 ms
ジャッジサーバーID
(参考情報)
judge14 / judge12
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 8 ms
25,368 KB
testcase_01 AC 9 ms
25,340 KB
testcase_02 AC 9 ms
29,300 KB
testcase_03 AC 9 ms
25,328 KB
testcase_04 AC 9 ms
25,284 KB
testcase_05 AC 7 ms
23,312 KB
testcase_06 AC 7 ms
23,232 KB
testcase_07 AC 9 ms
25,348 KB
testcase_08 AC 9 ms
25,332 KB
testcase_09 AC 8 ms
23,316 KB
testcase_10 AC 7 ms
23,236 KB
testcase_11 AC 8 ms
23,300 KB
testcase_12 AC 8 ms
23,288 KB
testcase_13 AC 9 ms
27,320 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
; compiling file "/home/judge/data/code/Main.lisp" (written 17 SEP 2023 06:52:50 AM):
; processing (SB-INT:DEFCONSTANT-EQX OPT ...)
; processing (SET-DISPATCH-MACRO-CHARACTER #\# ...)
; processing (DISABLE-DEBUGGER)
; processing (DECLAIM (FTYPE # ...))
; processing (DEFUN ENUM-DIVISORS ...)
; processing (DEFUN MAKE-DIVISORS-TABLE ...)
; file: /home/judge/data/code/Main.lisp
; in: DEFUN MAKE-DIVISORS-TABLE
;     (MAKE-ARRAY SUP :ELEMENT-TYPE 'LIST)
; 
; caught STYLE-WARNING:
;   The default initial element 0 is not a LIST.
;   See also:
;     The ANSI Standard, Function MAKE-ARRAY
;     The ANSI Standard, Function UPGRADED-ARRAY-ELEMENT-TYPE
; 
; caught STYLE-WARNING:
;   The default initial element 0 is not a LIST.
;   See also:
;     The ANSI Standard, Function MAKE-ARRAY
;     The ANSI Standard, Function UPGRADED-ARRAY-ELEMENT-TYPE

; processing (DEFMACRO DBG ...)
; processing (DEFMACRO DEFINE-INT-TYPES ...)
; processing (DEFINE-INT-TYPES 2 ...)
; processing (DECLAIM (INLINE PRINTLN))
; processing (DEFUN PRINTLN ...)
; processing (DEFCONSTANT +MOD+ ...)
; processing (DEFUN MAIN ...)
; processing (MAIN); 
; compilation unit finished
;   caught 2 STYLE-WARNING conditions


; wrote /home/judge/data/code/Main.fasl
; compilation finished in 0:00:00.207

ソースコード

diff #

;; -*- coding: utf-8 -*-
(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
           #\# #\> (lambda (s c p) (declare (ignore c p)) (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 (vector (integer 0 #.most-positive-fixnum)) &optional))
                enum-divisors))
(defun enum-divisors (x)
  "Enumerates all the divisors of X in O(sqrt(X)). Note that the resultant
vector is NOT sorted."
  (declare (optimize (speed 3))
           ((integer 0 #.most-positive-fixnum) x))
  (let* ((sqrt (isqrt x))
         (res (make-array (isqrt sqrt) ; FIXME: sets the initial size to x^1/4
                          :element-type '(integer 0 #.most-positive-fixnum)
                          :fill-pointer 0)))
    (loop for i from 1 to sqrt
          do (multiple-value-bind (quot rem) (floor x i)
               (when (zerop rem)
                 (vector-push-extend i res)
                 (unless (= i quot)
                   (vector-push-extend quot res)))))
    res))

;; Below is the variant that returns a sorted list.
;; (defun enum-divisors (n)
;;   "Returns the increasing list of all the divisors of N."
;;   (declare (optimize (speed 3))
;;            ((integer 1 #.most-positive-fixnum) n))
;;   (if (= n 1)
;;       (list 1)
;;       (let* ((sqrt (isqrt n))
;;              (result (list 1)))
;;         (labels ((%enum (i first-half second-half)
;;                    (declare ((integer 1 #.most-positive-fixnum) i))
;;                    (cond ((or (< i sqrt)
;;                               (and (= i sqrt) (/= (* sqrt sqrt) n)))
;;                           (multiple-value-bind (quot rem) (floor n i)
;;                             (if (zerop rem)
;;                                 (progn
;;                                   (setf (cdr first-half) (list i))
;;                                   (setf second-half (cons quot second-half))
;;                                   (%enum (1+ i) (cdr first-half) second-half))
;;                                 (%enum (1+ i) first-half second-half))))
;;                          ((= i sqrt) ; N is a square number here
;;                           (setf (cdr first-half) (cons i second-half)))
;;                          (t ; (> i sqrt)
;;                           (setf (cdr first-half) second-half)))))
;;           (%enum 2 result (list n))
;;           result))))

(defun make-divisors-table (sup)
  "Returns a vector of length SUP whose each cell, vector[INDEX], is the
increasing list of every divisor of INDEX. Note that vector[0] = NIL."
  (declare ((integer 0 #.most-positive-fixnum) sup))
  (let ((result (make-array sup :element-type 'list))
        (tails (make-array sup :element-type 'list))) ; preserves the last cons
    (declare (optimize (speed 3) (safety 0)))
    (loop for i from 1 below sup
          for cell = (list 1)
          do (setf (aref result i) cell
                   (aref tails i) cell))
    (when (>= sup 1)
      (setf (aref result 0) nil))
    (loop for divisor from 2 below sup
          do (loop for number from divisor below sup by divisor
                   do (setf (cdr (aref tails number)) (list divisor))
                      (setf (aref tails number) (cdr (aref tails number)))))
    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 main ()
  (let* ((a (read))
         (b (read))
         (divisors (enum-divisors a)))
    (sb-int:dovector (x divisors)
      (when (zerop (mod x b))
        (write-line "YES")
        (return-from main)))
    (write-line "NO")))

#-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 "C:/msys64/usr/bin/cat.exe" '("/dev/clipboard") :output out)))

#+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)))
0