※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 25632번 문제인 소수 부르기 게임이다.
문제는 아래 링크를 확인하자.

https://www.acmicpc.net/problem/25632 

 

25632번: 소수 부르기 게임

용태가 부를 수 있는 소수는 $11, 13, 17$이고, 유진이가 부를 수 있는 소수는 $13, 17, 19$이다. 둘 다 최선을 다해서 플레이한다면 $13 → 17 → 11 → 19$로 진행될 수 있다. 용태가 더 이상 부를 소수가

www.acmicpc.net

먼저 1000 이하의 각 양의 정수가 소수인지를 판별해두자. 개수가 적으므로 각 정수 x를 x미만의 양의 정수로 각각 나누어떨어지는지 확인해도 문제를 해결하기에 충분하다. 글쓴이는 에라토스테네스의 체를 이용했다.

 

이제 용태가 부를 수 있는 수의 범위에 있는 소수의 개수, 유진이가 부를 수 있는 수의 범위에 있는 소수의 개수와 둘다 부를 수 있는 소수의 개수를 각각 구해두자.

 

용태와 유진이의 최선의 전략은 "둘다 부를 수 있는 소수"들을 먼저 부르고 남은 부를 수 있는 소수(자신만이 부를 수 있는 소수)들을 나중에 부르는 것이다. 자신의 차례가 지날 때마다 "자신이 부를 수 있는 소수"의 개수는 똑같이 하나씩 줄어들게 되는데 이 때 "상대방이 부를 수 있는 소수"의 개수를 하나 더 줄일 수 있는지 없는지의 여부에 차이점이 있다고 생각하면 이해하기 쉬울 것이다.

 

아래는 제출한 소스코드이다.

#include <iostream>
using namespace std;

int sieve[1001];

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	sieve[0] = sieve[1] = 1;
	for (int i = 2; i < 1001; i++) {
		if (sieve[i]) continue;
		for (int j = i * i; j < 1001; j += i) sieve[j] = 1;
	}

	int L1, R1, L2, R2; cin >> L1 >> R1 >> L2 >> R2;
	int L3 = max(L1, L2), R3 = min(R1, R2);

	int yt = 0, yj = 0, common = 0;
	for (int i = L1; i <= R1; i++) {
		if (sieve[i] == 0) yt++;
	}
	for (int i = L2; i <= R2; i++) {
		if (sieve[i] == 0) yj++;
	}
	for (int i = L3; i <= R3; i++) {
		if (sieve[i] == 0) common++;
	}
	
	while (1) {
		if (yt + common == 0) {
			cout << "yj";
			return 0;
		}
		if (common) yt--, common--, yj--;
		else yt--;
		if (yj + common == 0) {
			cout << "yt";
			return 0;
		}
		if (common) yt--, common--, yj--;
		else yj--;
	}
}
728x90

+ Recent posts