Processing math: 100%
본문 바로가기

분할 정복을 이용한 거듭제곱/정수 거듭제곱

백준 15710번: xor 게임

www.acmicpc.net/problem/15710

 

15710번: xor 게임

첫째 줄에 정수 a, b (0 ≤ a, b < 231), n(0 < n ≤ 109)이 공백으로 구분되어 주어진다. 

www.acmicpc.net


xor 연산에 대해 잘 모르면 해결하기 어려운 문제입니다.

 

먼저 몇 가지 예시를 통해 생각해봅시다.

 

예를 들어, 10111011(2) 과 xor연산을 해서 00000111(2) 이 되는 수가 있을까요?

 

네, 10111100(2) 이 바로 그런 숫자입니다.

 

그러면 10111011(2) 과 xor연산을 해서 11100111(2)이 되는 수는 있을까요?

 

네, 01011100(2) 이 바로 그런 숫자입니다.

 

비단 10111011(2) 뿐만이 그런게 아니라, 일반적으로 모든 a,b 에 대해 a xor x = b의 근 x가 항상 존재하고, 이 근은 유일합니다.

 

따라서 게임의 N1번째 턴의 결과로 chogahui05가 가진 카드에 적힌 숫자가 X라고 한다면,

 

chogahui05는 N번째 턴에서 반드시 X와 xor연산하여 b가 나오는 값을 선택할 수 있습니다. (Xb의 값에 상관없이!)

 

즉 게임의 과정에서 N번째 턴의 결과가 b가 되기 위해 고를 수 있는 카드는 반드시 한 개 존재하며

 

그 외의 턴에서 고를 수 있는 카드는 231개가 됩니다.

 

따라서 N이 주어졌을 때 (231)N1=2147483648N1(109+7)로 나눈 나머지를 구해주면 해결되는 문제입니다.

 

코드는 다음과 같습니다.

 

#include <stdio.h>
#define mod 1000000007

long long power_modular (long long base, int power);

int main() {
	int a, b, n;
	scanf("%d %d %d", &a, &b, &n);
	printf("%lld", power_modular(2147483648ll, n-1));
	return 0;
}

long long power_modular (long long base, int power) {
	base %= mod;
	long long result = 1;
	while(power) {
		if (power % 2) {
			result = (result * base) % mod;
		}
		base = (base * base) % mod;
		power /= 2;
	}
	return result;
}

 

(C11, 1116KB, 0ms, 제출번호 26406084)


2147483648N1231×(N1) 으로 해석하여 구할 수도 있습니다.

 

다만 그 경우엔 power에 들어갈 값이 int범위를 초과할 수 있어 long long으로 바꿔주어야합니다.

 

글쓰고 있는 시점에서 적용중인 코드 하이라이팅 스크립트에서 2147483648에 postfix로 붙인 LL을 감지 못하고 있습니다만,

 

2147483648이 long long임을 나타내기 위해 postfix로 LL을 붙여주었습니다.

 

modulo가 소수이고 N109+7이므로 base자리에 2를 넣고 페르마의 소정리를 써서

 

power자리에 31×(N1)(109+6)으로 나눈 값을 넣어도 될 것 같습니다.