ARC 109 | C - Large RPS Tournament

12875 단어 경업자dptech

문제.


https://atcoder.jp/contests/arc109/tasks/arc109_c

해법


2^k는 1\leqn, k\leq100이기 때문에 참가 인원이 커지고 우직하게 하면 TLE가 된다.
만약에 s가 예시 1을 입력한 것처럼RPS 다음과 같이 같은 승리자를 반복한다.

이에 따라 s의 문자 수를 짝수로 만들기 위해 토너먼트 결과를 1부터 k까지 배열하고, 다음 토너먼트에서 활용하면 최종 승자가 늘어날 것으로 보인다.

코드


Tips 설치

  • 만약 n이 홀수라면 실현하기 어렵다. 따라서 n이 홀수일 때 n은 ss로서 짝수로 여겨진다
  • 가위바위보의 승부는 끼워넣기unordered_map
  • DP 또는 약간의 탐욕법
  • #include <bits/stdc++.h>
    
    #include <atcoder/all>
    
    using namespace std;
    using namespace atcoder;
    using ll = long long;
    using ld = long double;
    using uint = unsigned int;
    using ull = unsigned long long;
    const int MOD = 1e9 + 7;
    
    unordered_map<char, unordered_map<char, char>> mp = {
        {'R', {{'R', 'R'}, {'P', 'P'}, {'S', 'R'}}},
        {'S', {{'S', 'S'}, {'R', 'R'}, {'P', 'S'}}},
        {'P', {{'P', 'P'}, {'R', 'P'}, {'S', 'S'}}},
    };
    
    int main() {
      ll n, k;
      string s;
      cin >> n >> k >> s;
      if (n % 2 == 1) {
        // nが奇数だと計算しにくいので偶数にする
        s = s + s;
      }
      n = s.size();
      // dp[k][i] = k回目のじゃんけんの勝者を入れる
      vector<vector<char>> dp(k + 1, vector<char>(n));
      for (int i = 0; i < n; i++) {
        dp[0][i] = s[i];
      }
      // 下からi番目のトーナメントの勝者をうめていく
      for (int i = 1; i <= k; i++) {
        // 半分記録する
        for (int j = 0; j < n / 2; j++) {
          dp[i][j] = mp[dp[i - 1][2 * j]][dp[i - 1][2 * j + 1]];
        }
        // 残りは左と同じ
        for (int j = n / 2; j < n; j++) {
          dp[i][j] = dp[i][j - n / 2];
        }
      }
      cout << dp[k][0] << endl;
    }
    

    참고 자료

    좋은 웹페이지 즐겨찾기