蓝桥杯 PREV-14 高僧斗法(Nim游戏)

题目链接:

http://lx.lanqiao.cn/problem.page?gpid=T37

思路:

1.假设从 1 1 1开始给这 n n n个小和尚从左往右编号,那么编号为 1 , 2 , 3 , . . . , n 1,2,3,...,n 1,2,3,...,n
2.我们按照一奇一偶的方式给他们组队,结果为 ( 1 , 2 ) , ( 3 , 4 ) , . . . , ( n − 1 , n ) (1,2),(3,4),...,(n-1,n) (1,2),(3,4),...,(n1,n) ( 1 , 2 ) , ( 3 , 4 ) , . . . ( n − 2 , n − 1 ) , n (1,2),(3,4),...(n-2,n-1),n (1,2),(3,4),...(n2,n1),n,我们可以知道每一个偶数都必定有一个奇数与它组队;
3.每一队,移动序号为奇数的小和尚可以看成从这堆石子里拿走一些石子,而移动序号为偶数的小和尚可以看成从这堆石子里添加一些石子;
4.此时问题就已经转化成了Nim游戏的一个小变形,算出对手的必败态即可;

代码:

#include<bits/stdc++.h>

using namespace std;

int n, sum, a[105]; 

int main() {
    
    
#ifdef MyTest
	freopen("Sakura.txt", "r", stdin);
#endif
	while(~scanf("%d", &a[n])) ++n;
	for(int i = 0; i + 1 < n; i += 2) {
    
    
		sum ^= a[i + 1] - a[i] - 1;
	}
	for(int i = 0; i + 1 < n; i += 2) {
    
    
		int d = a[i + 1] - a[i] - 1;
		if(d > (sum ^ d)) {
    
    
			printf("%d %d", a[i], a[i] + d - (sum ^ d));
			return 0;
		}
		int x = (sum ^ d) - d;
		if(i + 2 < n && x < a[i + 2] - a[i + 1]) {
    
    
			printf("%d %d", a[i + 1], a[i + 1] + x);
			return 0;
		}
	}
	puts("-1");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45228537/article/details/104779974