Boot camp for Beginners hard 001【D – Gathering Children】をpython解説

Boot camp for Beginners hard

Atcoder Problems という競プロを勉強する上でのコンテンツがあります。URL
今回は、hard100問の内、1問目を解説していきたいと思います。

問題名 【D – Gathering Children】

問題
LとRからなる文字列Sが与えられます。各マスには子供がいて、子供はLと書かれたマスなら左に行き、Rと書かれたマスなら右に行きます。この動作を10の100乗繰り返したら、子どもたちの配置はどうなるか

  • 入力
    S(文字列)
  • 出力
    10の100乗後の子供の位置

考察

愚直に計算したら、10の100乗の計算をしなければならないので、TLEです。
しかし、Sの制約が2 <= s <= 10**5なので、sについては全探索できそうです。なので、Sの1つ1つについて考えていきます。

規則性を見つける

今回の条件をよくよく考えてみると実は4つのパターンからなることがわかります

  1. パターン1 ・・・〇〇RR〇〇・・・の場合
    この場合は、10**100回やれば子供は右に寄ります
  2. パターン2・・・〇〇LL〇〇・・・の場合
    この場合は、10**100回やれば子供は左に寄ります
  3. パターン3 ・・・〇〇RL〇〇・・・の場合
    RLのところを子供は反復します。
  4. パターン4 ・・・〇〇LR〇〇・・・の場合
    Lよりも左側にいる子供はR側に行くことはなく、Rよりも右側にいる子供はL側に行くことはないです。

一応、これだけでも問題を解くことができるのですが、、、
せっかくなのでもう少し問題について考察を深めていきましょう。

Sの中身(R or L)の特徴について考える

今回の問題、試行を重ねてみると必ず ○○RL○○ となっているところに子供が集まります。
なぜなら、〇〇RL〇〇となっていた場合、Rよりも左側の子どもたちはRよりもLよりも左側に行くことができず、同様にLよりも右側にいる子どもたちは、Rよりも右側に行くことができないからです。

つまり、RLとなっているところの数だけ子どもたちが集まる場所があり、その場所に集まる子どもたちの範囲は、〇〇LR〇〇・となったRから、次の〇〇LR〇〇となったLの範囲までです。
(最初と最後のみ例外)

以下の場合だったら、子どもたちの集まる場所は太字の3箇所となる。(同系色が集まる範囲)
RRRRLLLRLRLLL

では次に「最終的にRとLどちらの位置になるか?」について考えていきます。

RLのどちらに移動するか

それは、i番目が奇数なら奇数番目のR or L の位置になります。

理由
RLは隣り合う場所なので、必ず、どちらかが偶数番目でもう一方が奇数番目になります。
今回、試行回数が10**100(偶数回)なので、最終的な盤面は、
i番目の数が偶数であれば、RLの偶数の方に集まり、奇数ならその逆の場所に集まるためです。

コード

import sys
def LI(): return list(map(int,sys.stdin.readline().rstrip().split()))
def II(): return int(sys.stdin.readline())
def MI(): return map(int,sys.stdin.readline().rstrip().split())
def S(): return sys.stdin.readline().rstrip()

#入力を受け取るためのスニペット

box = S()
index = [0,]
check = []
ans = [0 for i in range(len(box))]
Even_cnt = 0
Odd_cnt = 0
gather = 0


for i in range(len(box)-1):
    if box[i] == box[i+1]:
        if i%2 == 0:
            Even_cnt += 1
        else:
            Odd_cnt += 1
    elif box[i] == "R" and box[i+1] == "L":
        gather = i
        if i%2 == 0:
            Even_cnt += 1
            flg = True
        else:
            Odd_cnt += 1
            flg = False
    
    elif box[i] == "L" and box[i+1] == "R":
        if i%2 == 0:
            Even_cnt += 1
        else:
            Odd_cnt += 1
        
        if flg:
            ans[gather] = Even_cnt
            ans[gather+1] = Odd_cnt
        else:
            ans[gather] = Odd_cnt
            ans[gather+1] = Even_cnt
        
        Odd_cnt = 0
        Even_cnt = 0

if (len(box)-1) %2 == 0:
    Even_cnt += 1
else:
    Odd_cnt += 1

if flg:
    ans[gather] = Even_cnt
    ans[gather+1] = Odd_cnt
else:
    ans[gather] = Odd_cnt
    ans[gather+1] = Even_cnt

print(*ans,sep = " ")

まとめ

制約をみて、絶対は計算量オーバーするであろう問題は、規則性を使う問題が多いです。
なので、今回みたいな問題のときでも、手を動かしてみて、規則性を見つけ解決の糸口にしてみてください!!

次の問題【B – Kleene Inversion】

コメント

タイトルとURLをコピーしました