본문 바로가기
Problem Solving/Topcoder

SRM 330 Div.1

by hongjun7 2016. 4. 21.

250(Easy) : 문제 링크

System> hongjun7 has submitted the 250-point problem for 242.56 points

class Arrows {
	public:
	int longestArrow(string s) {
		int res = -1;
		int n = s.size();
		for (int i = 0; i < n; i++) {
			for (int j = i; j < n; j++) {
				if (s[i] == '<') {
					int ok = 1;
					for (int k = i + 1; k <= j; k++) if (s[k] != s[i + 1]) ok = 0;
					if (ok) {
						if (i + 1 > j || s[i + 1] == '-' || s[i + 1] == '=') res = max(res, j - i + 1);
					}
				}
				if (s[j] == '>') {
					int ok = 1;
					for (int k = i; k < j; k++) if (s[k] != s[j - 1]) ok = 0;
					if (ok) {
						if (i > j - 1 || s[j - 1] == '-' || s[j - 1] == '=') res = max(res, j - i + 1);
					}
				}
			}
		}
		return res;
	}
};

500(Medium) : 문제 링크

문제를 요약하면 다음과 같다. prefix-free set을 집합의 모든 두 원소 쌍 중 어느 하나가 다른 하나의 prefix가 되지 않는 것으로 정의한다. 이 때, string set이 주어지면 그 set에서 prefix-free set을 찾는 것이 문제의 요구사항이다. string set의 크기는 50개 이하이며, 각 string의 길이도 50이하이다.

문제를 보고 트라이(trie)를 떠올리는데 5분 정도가 소요되었다.

트라이를 떠올리고도 counting하는 방법에 대해서 15분 정도 고민했었다. 결론부터 얘기하면, 트라이의 어떤 노드 x에 대해서 자식도드들 y_i들이 있을 때에 y_i들의 부트리에 대한 답들을 +1한 걸 다 곱한 후 -1하면 공집합을 제외한 걔네들끼리의 모든 prefix-free set의 개수가 된다. 왜냐하면 최초의 공통 조상이 x인데, x를 제외하면 prefix가 성립되지 않으니까. 여기다가 x_i가 finishing node(string의 끝)이면 +1해주면 된다. 주의할 점으로 문제에서 공집합도 prefix-free set으로 간주한다고 했으니까 트라이의 슈퍼노드도 finishing node라고 해주면 된다.

System> hongjun7 has submitted the 500-point problem for 248.81 points

int n, m;
int d[2555][26], fin[2555];
class PrefixFreeSubsets {
public:
	long long go(int x) {
		int cnt = 0;
		long long a = 1;
		for (int i = 0; i < 26; i++) {
			if (d[x][i] != -1) {
				++cnt;
				long long y = go(d[x][i]);
				a *= (y + 1);
			}
		}
		return (fin[x] == 1) + a - 1;
	}
	long long cantPrefFreeSubsets(vector <string> words) {
		n = words.size();
		memset(d, -1, sizeof(d));
		long long res = 0;
		for (int i = 0; i < n; i++) {
			string s = words[i]; int sn = s.size(); int p = 0;
			for (int j = 0; j < sn; j++) {
				int x = s[j] - 'a';
				if (d[p][x] == -1) {
					++m;
					d[p][x] = m;
				}
				p = d[p][x];
			}
			fin[p] = 1; //no duplicate
		}
		fin[0] = 1;
		res = go(0);
		return res;
	}
};

1000(Hard) : 문제 링크

System> hongjun7 has submitted the 1000-point problem for 664.67 points

int N, x[22], res, K;
bool d[4000005];
class LongLongNim {
public:
	int solve(int M, vector <int> x) {
		memset(d, 0, sizeof(d));
		res = 0;
		N = M; K = x.size();
		if (N > 1e6) {
			N = 1e6;
			for (int i = 1; i <= N; i++) {
				for (int j = 0; j < K; j++) {
					if (i >= x[j]) {
						if (d[i - x[j]] == 0) d[i] = 1;
					}
				}
			}
			int p = 1e6;
			for (int i = 1; i <= p; i++) {
				if ((p - i + 1) & 1) continue;
				int r = (p - i + 1) / 2;
				bool ok = 1;
				for (int k = i; k < i + r; k++) if (d[k] != d[k + r]) { ok = 0; break; }
				if (ok) {
					int c = 0;
					for (int k = p + 1; k <= N; k++) {
						if (d[k] != d[i + c]) { ok = 0; break; }
						c++;
						if (c == r) c = 0;
					}
					if (ok) {
						for (int k = 1; k < i; k++) res += (d[k] == 0);
						for (int k = 0; k < r; k++) res += (d[i + k] == 0)*((M - i - k) / r + 1);
						return res;
					}
				}
			}
		}
		else {
			for (int i = 1; i <= N; i++) {
				for (int j = 0; j < K; j++) {
					if (i >= x[j]) {
						if (d[i - x[j]] == 0)
							d[i] = 1;
					}
				}
				if (!d[i]) ++res;
			}
			return res;
		}
	}
	int numberOfWins(int maxN, vector <int> moves) {
		int res = solve(maxN, moves);
		return res;
	}
};

'Problem Solving > Topcoder' 카테고리의 다른 글

SRM 675 Div.1 LimitedMemorySeries1  (3) 2016.06.21
SRM 380 Div.2  (0) 2016.04.22
SRM 683 Div.1  (0) 2016.03.07
SRM 682 Div.1  (0) 2016.02.23
SRM 679 Div.1  (0) 2016.02.22

댓글