回答まとめはこちら
問題は下記。
1 から 4 の数字を使って作る n 桁の整数のうち、9 の倍数となるものの個数を F(n) と定義します。例えば、F(1) = F(2) = 0、F(3) = 10、F(4) = 40 となることが確かめられます。
標準入力から、自然数 n(1 ≦ n ≦ 20)が与えられます。標準出力に F(n) の値を出力するプログラムを書いてください。
1111…から4444…まで全通り生成して数えていては終わらないので、9の剰余で分類します。すなわち、1から4の数字を使って作るn桁の数字のうち、9で割ったあまりがrになるものの個数をとすると、
の漸化式になります。
これをrubyで計算し、F(n,0)を出力するコードが下記。Hashの引数が9で割ったあまりになっています。
n=gets.to_i
h={}
h[1]=h[2]=h[3]=h[4]=1
(1...n).each{|m|
tmp=Hash.new{|h,k| h[k]=0 }
h.each{|k,v|
(1..4).each{|i|
tmp[(i+k)%9]+=v
}
}
h=tmp
}
puts h[0]
最近始めたschemeで書いたのはこちら、末尾再帰といえば聞こえはいいけど、ループを再帰にして、状態を関数の引数で覚えている、というだけ。もっとスマートに書けると思うんだけど、引数10個くらいだしまぁいいよね、ということで。
(use-modules (ice-9 rdelim))
(define (solve i a0 a1 a2 a3 a4 a5 a6 a7 a8)
(if (= i 1)
a0
(+ (solve (- i 1)
(+ a5 a6 a7 a8)
(+ a6 a7 a8 a0)
(+ a7 a8 a0 a1)
(+ a8 a0 a1 a2)
(+ a0 a1 a2 a3)
(+ a1 a2 a3 a4)
(+ a2 a3 a4 a5)
(+ a3 a4 a5 a6)
(+ a4 a5 a6 a7)))))
(display (solve (string->number (read-line)) 0 1 1 1 1 0 0 0 0))
(newline)