Stunning Garbanzo
open main menu
Part of series: PS

1025 BOJ

/ 3 min read

문제

접근

다이내믹 프로그래밍과 파라매트릭 탐색으로 해결하였다.

기본적인 아이디어는 어렵지 않게 떠올릴 수 있으나, 괄호를 다루다 보니 생각할 것과 예외 처리해줘야 하는 것이 많아 이틀을 잡아먹었던 문제이다.

코드

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef const ll cll;
#define FOR(i, a, A) for (ll i = a; i < A; ++i)

cll N = 50, K = 2 ^ 50 - 1, Normal = N + 1, Total = N + 2,
    normal2Abnormal[4] = {0, 0, 0, 2}, change[4] = {-2, 0, 0, 2},
    nchange[4][2] = {{0, 2}, {0, 0}, {1, 1}, {2, 0}};
ll n, k, dp[N + 1][N + 2] = {{}}, sums[N + 4][N + 1][4] = {{{}}};
bool Accessible2Normal[4] = {true, false, true, true};
string prefixs[4] = {"((", "()", ")(", "))"};

int main(void) {
  ios::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);

  cin >> n >> k;

  dp[0][Normal] = 1;
  FOR(idx, 1, n + 1) FOR(prefix, 0, 4) {
    if (idx % 2) {
      continue;
    }

    ll prv = idx - 2;
    if (Accessible2Normal[prefix]) {
      dp[idx][normal2Abnormal[prefix]] += dp[prv][Normal],
          sums[Total][idx][prefix] += dp[prv][Normal],
          sums[normal2Abnormal[prefix]][idx][prefix] += dp[prv][Normal];
    } else {
      dp[idx][Normal] += dp[prv][Normal],
          sums[Total][idx][prefix] += dp[prv][Normal],
          sums[Normal][idx][prefix] += dp[prv][Normal];
    }

    dp[idx][0] += dp[prv][0], sums[Total][idx][prefix] += dp[prv][0],
        sums[0][idx][prefix] += dp[prv][0];

    FOR(lack, 1, n + 1) {
      if (lack % 2) {
        continue;
      }

      ll nlack = lack + change[prefix];
      if (!nlack) {
        dp[idx][Normal] += dp[prv][lack],
            sums[Total][idx][prefix] += dp[prv][lack],
            sums[Normal][idx][prefix] += dp[prv][lack];
      } else {
        dp[idx][nlack] += dp[prv][lack],
            sums[Total][idx][prefix] += dp[prv][lack],
            sums[nlack][idx][prefix] += dp[prv][lack];
      }
    }
  }

  string result;
  if (n % 2) {
    FOR(pos, 0, n) {
      result = ((k % 2) ? ")" : "(") + result;
      k /= 2;
    }
  } else {
    ll idx = n, total = (ll(1) << n) - dp[n][Normal], sidx = Normal, cnt = 0;
    if (k >= total) {
      result = "-1";
      goto END;
    }

    bool isAbnormal = false;
    while (idx > 0) {
      FOR(prefix, 0, 4) {
        ll sum = sums[Total][idx][prefix] - sums[sidx][idx][prefix];
        if (sum > k) {
          result = result + prefixs[prefix];
          if (!isAbnormal) {
            cnt -= nchange[prefix][0];
            if (cnt < 0) {
              isAbnormal = true, sidx = Total + 1;
            } else {
              cnt += nchange[prefix][1];
              sidx = cnt == 0 ? Normal : cnt;
            }
          }
          break;
        } else {
          k -= sum;
        }
      }

      idx -= 2;
    }
  }

END:
  cout << result << "\n";

  return 0;
}