CodeIQ 「ステップ・アップ・サム」問題
CodeIQ の Kawazoe さん出題の問題。
問題と他の方の解答が http://togetter.com/li/875421 にある。
とりあえず項数 1 の数列を許すとして考える。
項数が奇数のとき、m を項数とすると、(m によって定まる)初項 a(m) は
数列が整数列であるための必要十分条件は m が n の約数であること。
項数が偶数のとき、m を 初項+末項 とすると、項数は 、(m によって定まる)初項 b(m) は
数列が整数列であるための必要十分条件は m が n の奇数の約数であること。
初項が正整数となる数列の初項の総和を求めるには、m を n の奇数の約数の範囲で動かし、a(m), b(m) がそれぞれ正のものを選んで足し上げればよい。
m が n の奇数の約数のとき a(m), b(m) は整数、上式より なので、正整数となるのは a(m) と b(m) のうちのどちらか丁度一方で、それは
と書ける。
結局、求める値は
となる。但し m は n の奇数の約数の範囲で動かす。
n を引いているのは項数 1 の数列の寄与を取り除くため。
下が提出したコード。言語は Ruby。
n は標準入力から入力する。
素因数分解を利用しているので、 とかならほとんど計算時間はかからない。
require 'prime' def f(m, k) return (m - 2 * @n / m).abs / 2 + 1 unless @factor[k] (0..@factor[k][1]).map {|e| f(m * @factor[k][0] ** e, k + 1)}.inject(:+) end @n = gets.to_i @factor = Prime.prime_division(@n) p f(1, @n % 2 == 0 ? 1 : 0) - @n