ここのところ続いている、分割数の問題です。
前までの漸化式で解こうとしたら、時間がかかってだめ。
Wikipediaを見なおしてみると、別の漸化式があったのでこっちでやってみたら、まあ、なんとか。
式はこれ。 オイラーの五角数定理だそうな。
p(k) = p(k − 1) + p(k − 2) − p(k − 5) − p(k − 7) + p(k − 12) + p(k − 15) − p(k − 22) − ...
ここで出てくる数列 ( 1 2 5 7 12 15 22 ) は、負の数を含めた五角数で、ほんとはマイナス無限大から無限大までの整数に対する五角数の並び(…15 7 2 1 5 12 22…)を 1 で 折り返したもの。
また、p(0) = 1、負の数の場合を0として計算すると答えが出るらしい。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Problem 78 : 2012/4/19 | |
;;"Elapsed time: 158761.969222 msecs" | |
;; defn-memo is my macro for memoise function definition. | |
;; -> https://gist.github.com/1185886 | |
;; pentagonal | |
(defn pentagonal [n] | |
(/ (* n (- (* 3 n) 1)) 2)) | |
(defn-memo partition-num [n] | |
(cond (< n 0) 0N | |
(= n 0) 1N | |
:else (reduce +' | |
(map #(* (partition-num (- n %1)) %2) | |
(->> (mapcat #(vector % (- %)) (iterate inc 1)) | |
(map pentagonal ,,) | |
(take-while #(<= % n) ,,)) | |
(flatten (repeat [1 1 -1 -1])))))) | |
(defn pe78 [limit] | |
(first | |
(drop-while #(not= 0 (mod (second %) limit)) | |
(pmap #(vector % (partition-num %)) (iterate inc 1N))))) |
・ pentagonal
五角数を計算します。
・ partition-num
p(n) を計算します。
->> のところは、 1 -1 2 -2 3 -3 4 -4 を作って、 それぞれの五角数を求めて、kより大きいものを省いています。
それを p(k-?) の式にあてはめて、計算してます。
・ pe78
p(n) を1から順に計算して、limitで割って余りが無くなる最初のものを計算します。
0 コメント:
コメントを投稿