最終更新: 2012-02-29T17:34+0900
前のバージョンはここ(20110312p01.02)。step2を最適化*すると倍くらい速くなって 1分半(ウチのPC基準で。C++だとコンマ1秒)。それに伴い素因数の組み合わせを求める必要がなくなったので、100万要素の配列の配列が 100万要素の Fixnum配列になってメモリ使用量が再び数MBレベルになった。
LIMIT = 1_000_000 pfs = Array.new(LIMIT+1, 1) count = LIMIT*(LIMIT+1)/2 - 1 # 1) 2からLIMIT以下の分母 d につき d 通りの分子を予め計上する。 2.upto(LIMIT){|d| # 0) 2からLIMIT以下の分母 d に対して、 print d,"\r" d.step(LIMIT, d){|_| pfs[_] *= -d } if pfs[d] == 1 # 2) 分子が d で分母が d の倍数になるものを加減する。 count += pfs[d]/pfs[d].abs * (LIMIT/d)*(LIMIT/d+1)/2 if pfs[d].abs == d } p count
一週間後にはこのコードが理解できなくなってること請けあい。
ググった>「Dreamshire | Project Euler Problem 72 Solution」。φ関数の値を合計するとかで、Rubyでも10秒未満。Problem 69に出てきた関数だけど、その問題はインチキしたから理解してないんよね。
LIMIT = 1000000 phi = (0..LIMIT).to_a 2.upto(LIMIT){|n| n.step(LIMIT, n){|m| phi[m] *= (n-1.0)/n } if phi[n] == n } p phi.inject(&:+).floor-1
繰り返しの構造は似てるのにこの実行時間の差はなんだ? と思ったら print d,"\r"
の有無だけだった。俺のも同等に速い。
* 全体でみると同じ数字を足したり引いたりを繰り返してる気がしたので個々の dに特有の値だけを加減するように。