어흥

[백준 10422] 괄호 (C++) 본문

알고리즘/백준

[백준 10422] 괄호 (C++)

라이언납시오 2020. 4. 7. 23:59
728x90
반응형

문제 링크: https://www.acmicpc.net/problem/10422

 

10422번: 괄호

‘(‘, ‘)’ 문자로만 이루어진 문자열을 괄호 문자열이라 한다. 올바른 괄호 문자열이란 다음과 같이 정의된다. ()는 올바른 괄호 문자열이다. S가 올바른 괄호 문자열이라면, (S)도 올바른 괄호 문자열이다. S와 T가 올바른 괄호 문자열이라면, 두 문자열을 이어 붙인 ST도 올바른 괄호 문자열이다. (()())()은 올바른 괄호 문자열이지만 (()은 올바른 괄호 문자열이 아니다. 괄호 문자열이 주어졌을 때 올바른 괄호 문자열인지 확인하는 방법은 여러

www.acmicpc.net

1. 주의할 점

- 카탈란 수에 대해 알고 있어야 한다

- 입력받는 수가 홀수인 경우 0을 출력하고, 짝수인 경우 반으로 나눈 후 진행한다

- 페르마 소정리에 대해 알고 있어야 한다

- 시간복잡도를 Lg(N)으로 줄여야 한다

 

페르마 소정리에 대해 모르는 경우 11401의 해설에 적힌 페르마 소정리에 대해 이해한다

문제 링크: https://imnotabear.tistory.com/98

 

[백준 11401] 이항 계수 3 (C++)

문제 링크: https://www.acmicpc.net/problem/11401 11401번: 이항 계수 3 자연수 \(N\)과 정수 \(K\)가 주어졌을 때 이항 계수 \(\binom{N}{K}\)를 1,000,000,007로 나눈 나머지를 구하는 프로그램을 작성하시오...

imnotabear.tistory.com

 

2. 구현

- 괄호와 관련된 카탈란 수의 경우, 짝이 N개인 괄호를 통해 2nCn/(n+1)만큼의 올바른 괄호 문자열을 만들 수 있다

- 페르마의 소정리를 사용해 {2nCn/(n+1)} % MOD를 변형시킨다

{2nCn/(n+1)} % MOD

-> (2n)! % MOD / [{(n+1)! % MOD} * {n! % MOD}] %MOD

-> {(2n)! % MOD}*  [{(n+1)! % MOD} * {n! % MOD}]^(MOD-2) % MOD가 성립한다

- Factorial을 구하는 함수는 테스트 케이스가 돌때마다 하면 시간 낭비 -> 따로 빼서 구한다

- Pow를 구하는 함수는 Math.h 헤더에 있는 것을 사용할 경우, 지수만큼의 시간복잡도가 소요되서 TLE가 발생할 수 있다 -> Lg(지수) 의 시간복잡도가 소요되도록 Pow함수를 구현한다. 

#include <iostream>
using namespace std;

long long MOD = 1000000007, result;
long long fact[10001];

long long pow(long long val, long long idx) {
	if (idx == 0) return 1;
	else if (idx == 1) return val;
	if (idx % 2 == 0) {
		long long temp = pow(val, idx / 2);
		temp *= temp;
		temp %= MOD;
		return temp;
	}
	else {
		long long temp = pow(val, idx - 1);
		temp *= val;
		temp %= MOD;
		return temp;
	}
}

int main() {
	int test, len;
	cin >> test;
	fact[0] = 1;
	for (int i = 1; i <= 10000; i++) {
		fact[i] = fact[i - 1] * i;
		fact[i] %= MOD;
	}

	for (int i = 0; i < test; i++) {
		cin >> len;
		if (len % 2 == 1) {
			cout << 0 << '\n';
			continue;
		}
		len /= 2;
		long long up = fact[2 * len];
		long long down = fact[len + 1];
		down *= fact[len];
		down %= MOD;
		result = up * pow(down, MOD - 2);
		cout << result % MOD << '\n';
	}
	system("pause");
	return 0;
}
728x90
반응형

'알고리즘 > 백준' 카테고리의 다른 글

[백준 2668] 숫자고르기 (C++)  (0) 2020.04.09
[백준 17305] 사탕 배달 (C++)  (0) 2020.04.09
[백준 2225] 합분해 (C++)  (0) 2020.04.06
[백준 14225] 부분수열의 합 (C++)  (0) 2020.04.05
[백준 1826] 연료 채우기 (C++)  (0) 2020.04.04
Comments