Codeforces Round #587 (Div. 3) E2. Numerical Sequence (hard version)
問題概要
正整数 に対して、 を十進表記で書いたものをこの順に連結した文字列を とする。例えば "1234567891011"
である。
そして、 をこの順に連結した無限の長さの文字列を考える。与えられる 個の整数 に対して、この文字列の 番目の文字を答えよ。
制約
解法
各クエリに対する を単に と記します。また、問題概要に記したように文字列 を定めます。
まず、 番目の文字がどの に属するか調べる必要があります。これは の長さの合計を とすると、 を満たす最小の として求められるので二分探索できます。判定問題を解くために、ある固定した値 に対する の効率的な求め方を考えましょう。
の桁数を として、 なる桁数 を考えます。整数 に含まれる 桁の値を抜き出します。この最小値、最大値、値の個数をそれぞれ と書くことにすると、これらは以下のように計算できます。
やりたいことは文字列 の長さ合計を求めることです。これを について合計したものが になります。
ある についての計算を、さらに分けて考えます。 なる桁数 について、文字列 の中に 桁の整数が合計でいくつ入っているかを求めます。
- のとき、 それぞれに 桁の整数全てが1つずつ含まれています。 桁の整数は全部で 種類あるので、合計で 個の整数があります。
- のとき、 桁の整数は に1個、 に2個、...、 に 個含まれています。つまり等差数列の公式から、合計で 個の整数があります。
これに を掛けたものを全ての について合計すると の長さ合計が求められます。それをさらに について合計したものが になります。
これを用いて二分探索することで、 番目の文字がどの に属するか求められました。ここで求められた値を引き続き と記します。ここで とすると、求めたいのは の 番目の文字です。
ここで知りたいのは として並べられた整数 のうちどれに 番目の文字が含まれているかで、これはまたしても二分探索することで求められます。つまり 番目の文字を含むのは、 を満たす最小の です。
の計算方法は先ほどの に比べると簡単で、 の中に 桁の数がいくつ含まれるかを同じように計算し、それに を掛けたものを全て合計すれば良いです。
これで も特定できれば、その十進表記における 番目の数字が求める文字です。
ACコード
Submission #61031718 - Codeforces
計算量ですが、 が小さいので10の冪乗などの前計算などをしておかなくても余裕があります。二分探索・桁数 の全探索・10の冪乗で が4つくらい付いていると思います。
またオーバーフローに注意する必要があります。二分探索の初期値としてあまり大きな値を取りすぎると の値がオーバーフローしますが、実際に計算すると がだいたい になって の制約を超えるので、 の上側の初期値を としておくと良いでしょう。