K-ナッチ数列のn番目の項を高速に求める

ardririy
·

まえがき

↓の問題が話題に上がって,これBなの!?と思ったやつ.

Kが一般になるとABC-CかABC-Dぐらいの難易度な気がする.

問題

K-ナッチ数列は

a_1 = a_2 = .. = a_{K-1} = 0

a_k = 1

a_i = a_{i-K} + a_{i-K+1} + .. a_{i-1} (i > K)

で定められる.K,Nが与えられるので,a_Nを求めよ.ただし,a_Nは非常に大きくなる可能性があるので,10007で割ったあまりを出力すること.

制約

2sec, 1 <= K, N <= 10^6

方針

i番目の項について愚直に求めるとそれ以前のK項を合計する必要があり,それをN回繰り返すのでO(NK)となり間に合わない.

ここで,K-ナッチ数列の隣接する項を考えると,

a_i = a_{i-K} + a_{i-K+1} + .. a_{i-1}

a_{i+1} = a_{i-K+1} + .. a_{i-1} + a_{i}

と,計算の大部分がほとんど同じであることがわかる.であればK項を毎回合計せずとも,変化する部分のみを差分計算してあげることによってO(N)でもとまりそうです.

注意: O(N+K)ではなくO(N)なのは a_1 + a_2 + ... + a_k = 1なのではじめのK項の総和を求めておく必要がないため.

実装

はじめに挙げた問題に提出してるのでK=3で固定だけど,一般のKにたいしても十分高速で計算ができるはず.

コードテストで速度チェックやってみたけど十分高速.答えがあってるかわからないけど多分あってるでしょう.