B - 花壇の水やり / Watering the Flower Bed Editorial by admin
GPT 5.2 High概要
スプリンクラーの間隔 \(K\) を \(1 \le K \le N\) から選び、位置 \(1,1+K,1+2K,\ldots\) にある花 o の個数が最大になる値を求めます。
考察
スプリンクラーが水をまくのは、先頭から \(K\) 個おきの区画だけです。つまり(1-indexed で)
$\(1,\ 1+K,\ 1+2K,\ \ldots \le N\)\(
にある `o` の数を数えれば、その \)K$ で水やりできる花の数が分かります。
ここで素朴に「各 \(K\) について、全てのマスを見て『この位置は水をまく位置か?』を判定する」と、各 \(K\) に \(O(N)\) かかり全体で \(O(N^2)\) になってしまい、\(N=2\times 10^5\) では間に合いません。
重要な観察は、「水をまく位置だけを直接たどればよい」ということです。
\(K\) を固定したときに見るべき位置は \(1, 1+K, 1+2K, \ldots\) のみで、その個数は約 \(N/K\) 個です。
したがって、各 \(K\) について \(O(N/K)\) で数えられます。
例えば \(N=10, K=3\) なら見る位置は \(1,4,7,10\) の 4 箇所だけで十分です(他の位置は絶対に水をまかないため)。
アルゴリズム
- 文字列 \(S\) を配列 \(a\) に変換する(
oを 1、.を 0 とする)。 - \(K=1\) から \(N\) まで全探索する。
- 各 \(K\) について、\(i=0, K, 2K, \ldots\)(0-indexed)を順にたどり、\(a[i]\) を合計する。
- この合計が「その \(K\) で水やりできる花の数」
- その最大値を答えとして出力する。
コードでは range(0, N, k) を使うことで、「水をまく位置だけ」を効率よく列挙しています。
計算量
- 時間計算量: \(\displaystyle \sum_{K=1}^{N} O\!\left(\frac{N}{K}\right) = O(N \log N)\)
(調和級数 \(1+\frac12+\cdots+\frac1N = O(\log N)\) を用いる) - 空間計算量: \(O(N)\)(
o/.を 0/1 にした配列を持つため)
実装のポイント
位置は問題文では 1-indexed ですが、Python の配列は 0-indexed なので、先頭(位置 1)をインデックス 0 として
0, k, 2k, ...を見れば一致します。Sを毎回参照するより、a[i]が 0/1 の配列にしておくと加算が簡単になります。入力が大きいので
sys.stdin.readlineを使うと安心です。ソースコード
import sys
def main():
input = sys.stdin.readline
N = int(input().strip())
S = input().strip()
a = [1 if c == 'o' else 0 for c in S]
ans = 0
for k in range(1, N + 1):
s = 0
for i in range(0, N, k):
s += a[i]
if s > ans:
ans = s
print(ans)
if __name__ == "__main__":
main()
この解説は gpt-5.2-high によって生成されました。