Official

D - Many Repunit Sum Editorial by vwxyz


原案:toam

\(1\)\(A_i\) 個つなげた整数を \(N\) 個作り、それらを足すという方針には、\(2\) つの問題があります。
\(1\) つ目は計算量で、普通に\(N\) 個の整数を作ったのでは \(O(N^2)\) かかってしまいます。
\(2\) つ目は多倍長整数です。いくつかの言語では多倍長整数を使う場合は自分で実装する必要があります。
これらを両方解決する方法を考えます。

\(B_i=\sum_{j=0}^{A_i-1}{10^j}\) なので、\(\sum_{i=1}^{N}{B_i}\) において \(10^k\) が足される回数を \(C_k(k=0,1,,2\dots)\) と置くと、\(C_k\)\(k \lt A_i\) を満たす \(i\) の個数であり、逆に、\(A_i\)\(C_0,C_1,\dots,C_{A_i-1}\)\(1\) 寄与させることになります。
\(C_0,C_1,\dots,C_{N-1}\) は累積和を用いることで \(O(N)\) で求めることができます。
また、\(C_N,C_{N+1},\dots\)\(0\) です。

\(i=0,1,2,\dots\) の順に以下の処理を行います。

\(\frac{C_i}{10}\)\(C_{i+1}\) に足し、\(C_i\)\(10\) で割った余りに置き換える。ただし、\(N \leq i, \; C_i=0\) の場合は操作を終了する。

この処理を行うと、最終的に \(C_0,C_1,C_2,\dots\) はすべて \(9\) 以下の整数になっており、\(C_i\) が、求める答えの下から \(i+1\) 桁目を表していることがわかります。
足し算の筆算の処理を想像するとわかりやすいと思います。

これは stack などのデータ構造を用いると実装できます。
計算量は \(O(N)\) です。

posted:
last update: