Problem Solving/백준 1일 1커밋

백준 4342 유클리드 게임 - C++

HWAN JJ 2022. 1. 24. 18:52

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

 

4342번: 유클리드 게임

유클리드 게임은 두 명이서 하는 게임이고, 자연수 2개로 시작한다. 동혁이와 동규는 유클리드 게임을 하려고 한다. 동혁이가 먼저 시작한다. 동혁이는 큰 수를 작은 수의 배수만큼 뺀다. 이때,

www.acmicpc.net

다음 포스팅부터는 게임 문제 말고 다른 문제로 돌아오겠습니다..

 

 

<풀이>

 

크게 보면 간단한 문제? 

 

경우를 좀 나눠 생각하면 명쾌한 풀이가 나온다 . A > B인 A,B를 입력으로 받은 두 숫자라고 하면,

 

1. A = KB, 즉, A가 B의 배수인 경우, 해당 턴에 (A, B).를 받은 사람이 바로 승리한다. 

2. A = KB + M (M!=0) 인 경우, K가 1인 경우와 1이 아닌 경우로 나눠지는데 

   2-1 K =1인 경우, 해당 턴의 플레이어에게는 선택권이 없다. A-B를 하는 방법밖에 없다.

   2-2 반면, K > 1인 경우, 해당 턴의 플레이어는 2가지 선택지가 있는데, 

   1) 만약, (B, M)을 상대에게 넘기면 지는 경우, A - (K-1)B 를 넘겨주면 상대방은 다시 2-1 상태로 가기 때문에 승리

   2) 넘기면 이기는 경우, A - KB를 간단히 넘겨주면 승리

 

즉, K > 1이 넘는 경우에서 턴을 잡은 경우, 무조건 승리 가능하다.

 

#include <iostream>

using namespace std;
using ll = long long;

int solve(ll a, ll b, bool player) {
	// a > b

	if (a % b == 0) {
		return player;
	}

	if (a / b == 1) {
		// 현재 플레이어에게 조정 권한 X
		return solve(b, a % b, !player);
	}
	else {
		// a = kb + m이라고 했을 때,
		// (b, m)이 만약 현재 플레이어가 넘겨주면 지는 숫자 조합이면,
		// 현재 플레이어는 (k-1)만 빼고 넘겨주면 (b,m)을 받아올 수 있다.
		// 반대로 이기는 판이면, kb를 빼고 넘겨주면 상대방에게 (b, m) 강요 가능
		return player;
	}
}

int main(void) {

	ios_base::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);

	ll a = 1, b = 1;
	while (1) {
		cin >> a >> b;
		if (a + b == 0) break;
		if (a < b) {
			ll tmp = a;
			a = b;
			b = tmp;
		}
		if (!solve(a, b, 0))
			cout << "A wins" << "\n";
		else
			cout << "B wins" << "\n";
	}
	return 0;
}