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()