ABC132 F問題:Small Products

問題. Small Products

正整数からなる長さ  K の数列で,隣り合うどの 2 要素の積も  N 以下となるものが何通りあるか求めよ.

制約 1 \le N \le 10^9,  2 \le K \le 100

解法.動的計画法 + 累積和

まず,数列の各要素は 1 以上  N 以下であることが分かる.そこで,dp[i][j] を長さ  i で末尾の要素が  j となる条件を満たす数列の数として動的計画法をしたくなるが  O(N^2 K) 時間かかるので高速化が必要である.
ここで,隣り合う2要素の遷移を考えたとき下の図のようにブロックに分割することができる(2つのブロック内のどの要素との積も  N 以下のときブロック間を矢印で結んでいる).同じブロック内なら遷移先は同じとなるので状態数を減らすことができる.このブロック数は  N に関して単調増加となり, N = 10^9 のとき  63,244 個のブロックに分割することができるので,上の動的計画法 O(K S^2) 時間に高速化できた( S はブロック数で  S \le 63,244).また,遷移は連続するブロックとなるので各  i の遷移の前で累積和を求めることによって  O(K S) 時間で求めることができる.
       f:id:tatanaideyo:20190630052743p:plain:w250

計算時間 O(K S + S \log S)

本番で解けなかったけど後で自力で解けたので嬉しい.バグらせずに細かい部分を速く実装するのが課題.あとで  S のサイズを考えてみる.

追記.
解説 によると  S = \sqrt{N} らしい.下図の横軸は  x = 1, \ldots, N で,縦軸が  \lfloor N / x \rfloor の値.縦軸の値の種類数が  S に対応.床関数で潰れて  S N に比べて少ないのが分かる(証明は解説が分かりやすい).
f:id:tatanaideyo:20190630095812p:plain:w300 f:id:tatanaideyo:20190630100313p:plain:w300