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