题解取火柴游戏

Posted h-lka

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解取火柴游戏相关的知识,希望对你有一定的参考价值。

Link

( ext{Solution:})

回顾一下(Nim)游戏那个优美结论的( ext{conclusion:})

将所有石子数量异或起来,若和为(0)则必败,否则必胜。(先手)

那分以下情况考虑:

首先是全(0:)此时必败,显然异或和为(0).

然后是异或和不为(0)的状态:那我们必定可以找到一个(a_i),将它改变,使得异或和为(0).

因为二进制异或下的某一位是(1)的话则一定有奇数个数在此处是(1).那么我们随意找一个,令异或和为(k).将(a_i o a_i ext{^} k)则这个数必然比原来的(a_i)小。因为最高位改变了。

第三种情况是异或和为(0)时不存在一种移动使得下一步的异或和依旧是(0).

因为如果让(a_i o a_i*)成立的话,则必然有(a_i*=a_i),是一个不合条件的移动。

那么对于这个题:第一步用(Nim)和判断是不是必败,第二步枚举每一个队看看能不能修改即可。

#include<bits/stdc++.h>
using namespace std;
int n,a[5000010],s;
pair<int,int>p;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%d",a+i);
	for(int i=1;i<=n;++i)s^=a[i];
	if(s==0){
		puts("lose");
		return 0;
	}
	for(int i=1;i<=n;++i){
		int S=s;
		S^=a[i];
		if(a[i]>=S){
			p.first=a[i]-S;
			p.second=i;
			a[i]-=p.first;
			break;
		}
	}
	printf("%d %d
",p.first,p.second);
	for(int i=1;i<=n;++i)printf("%d ",a[i]);
	puts("");
	return 0;
}

以上是关于题解取火柴游戏的主要内容,如果未能解决你的问题,请参考以下文章

P1247 取火柴游戏

P1247 取火柴游戏

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

P1247 取火柴游戏

P1247 取火柴游戏(异或理论)

取火柴游戏||Nim博弈