ybtoj 博弈论课堂过关luogu P1247luogu P2197模板nim 游戏 & 取火柴游戏 &例题1取火柴游戏

Posted SSL_ZZL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ybtoj 博弈论课堂过关luogu P1247luogu P2197模板nim 游戏 & 取火柴游戏 &例题1取火柴游戏相关的知识,希望对你有一定的参考价值。

【例题1】取火柴游戏 & [ZJOI2009] 取石子游戏 & 【模板】nim 游戏


Link

ybtoj 【博弈论课堂过关】【例题1】取火柴游戏
luogu P1247 取火柴游戏
luogu P2197 【模板】nim 游戏
题面//因为不知道侵不侵权所以就是题面是私密的,有账号的直接看转送门就可了


题目大意

有 n 个火柴堆,第 i 堆火柴堆有 a[i] 根火柴
你和人机轮流取火柴

  • 每次只能取一堆的火柴(不能跨堆取)
  • 每次必须取,可以全部取完

拿走最后一根火柴的一方赢


解题思路

来来来,各位先食用一些论证
结论为,这种NIM游戏,先手赢,当且仅当 A 1   x o r   A 2   x o r . . .   A n   =   a n s   ≠ 0 A_1\\ xor\\ A_2\\ xor...\\ A_n\\ =\\ ans\\ ≠ 0 A1 xor A2 xor... An = ans =0

那么方案怎么算呢??
当先手赢时,一定存在一个 A a n s w   x o r   a n s   <   A a n s w A_{answ}\\ xor\\ ans\\ <\\ A_{answ} Aansw xor ans < Aansw
这个 A a n s w   x o r   a n s A_{answ}\\ xor\\ ans Aansw xor ans就是第一步取完,剩下的火柴
那么 A a n s w   −   ( A a n s w   x o r   a n s ) A_{answ}\\ -\\ (A_{answ}\\ xor\\ ans) Aansw  (Aansw xor ans)就是第一步取的火柴


Code

#include <iostream>
#include <cstdio>

using namespace std;

int n, a[501000], ans;

int main() {
	scanf("%d %d", &n, &a[1]);
	ans = a[1];
	for(int i = 2; i <= n; i ++) {
		scanf("%d", &a[i]);
		ans ^= a[i];
	}
	if(ans == 0) printf("Lose");
		else {
			for(int i = 1; i <= n; i ++)
				if((a[i] ^ ans) < a[i]) {
					printf("%d %d\\n", a[i] - (a[i] ^ ans), i);
					for(int j = 1; j < i; j ++)
						printf("%d ", a[j]);
					printf("%d ", a[i] ^ ans);
					for(int j = i + 1; j <= n; j ++)
						printf("%d ", a[j]);
					break;
				}
		}
}

以上是关于ybtoj 博弈论课堂过关luogu P1247luogu P2197模板nim 游戏 & 取火柴游戏 &例题1取火柴游戏的主要内容,如果未能解决你的问题,请参考以下文章

luogu P4513ybtoj线段树课堂过关例题3小白逛公园

ybtoj 单调队列课堂过关luogu P1886例题1滑动窗口

luogu UVA10559 ybtoj 区间DP课堂过关 例题3消除木块 & 方块消除 Blocks

luogu P4170ybtoj 区间DP课堂过关 例题2木板涂色 & [CQOI2007]涂色

luogu P1352ybtoj 树形DP课堂过关 例题1树上求和 & 没有上司的舞会

luogu P1880ybtoj 区间DP课堂过关 例题1石子合并 & [NOI1995] 石子合并