| ps | |
|---|---|
| 링크 | acmicpc.net/… |
| 출처 | BOJ |
| 문제 번호 | 12108 |
| 문제명 | 약수 지우기 게임 2 |
| 레벨 | 플래티넘 2 |
| 분류 |
게임 이론 |
| 시간복잡도 | O(n*2^n) |
| 인풋사이즈 | n<=30 |
| 사용한 언어 | Python 3.11 |
| 제출기록 | 73500KB / 1864ms |
| 최고기록 | 148ms |
| 해결날짜 | 2023/07/14 |
"""Solution code for "BOJ 12108. 약수 지우기 게임 2".
- Problem link: https://www.acmicpc.net/problem/12108
- Solution link: http://www.teferi.net/ps/problems/boj/12108
Tags: [game theory]
"""
import functools
def iter_bitset(bitset):
while bitset:
lsb = bitset & -bitset
yield lsb.bit_length() - 1
bitset -= lsb
def main():
@functools.cache
def is_win_pos(pos):
for num in iter_bitset(pos):
if not is_win_pos(pos & ~divisors[num]):
return True
return False
N = int(input()) # pylint: disable=unused-variable
X = [int(x) for x in input().split()]
divisors = {}
for x_i in X:
divisors[x_i] = sum(1 << n for n in X if x_i % n == 0)
a_pos = sum(1 << n for n in X)
for a_take in X:
answer = []
b_pos = a_pos - divisors[a_take]
for b_take in iter_bitset(b_pos):
if not is_win_pos(b_pos & ~divisors[b_take]):
answer.append(b_take)
print(f'({a_take}) ', end='')
print(*answer if answer else 'A')
if __name__ == '__main__':
main()