HDU 4388 Stone Game II 博弈论 找规律

时间:2023-12-21 09:40:20

http://acm.hdu.edu.cn/showproblem.php?pid=4388

http://blog.csdn.net/y1196645376/article/details/52143551

好久没有写题了,再这么颓下去就要被彻底踩爆了(已经被彻底踩爆了)。

这道题是一道博弈论,从侧面向我们揭示了一个客观规律,取东西的博弈论(不是定理的话)大多数都是从二进制入手(虽然这道题题目很显然是和二进制有关)进行一系列的找规律。

这道题的正解也同样给了我们一种看题的思路,从最基本的条件看起,找题目的突破点或者规律。

题目大意:有n堆石子,某堆的石子数为x,每次操作将一堆石子分为k和k(xor)x两堆(k<x , k(xor)x<x)(两个人在一局游戏中分别有一次机会在分石子时将 k(xor)x的一堆变为2k(xor)x)。

直接看规则是很复杂的,但经过观察可以发现每次分石子后所有石子堆的二进制形式中的1的数目的奇偶性不变,而游戏结束状态即为每一堆二进制形式中1的个数都为1。

那么显然(并不那么显然)可以推得(推导过程就是找后继情况的先手后手必胜倒着推),设n+所有堆的石子数的二进制形式中1的个数的和为cnt,那么cnt是奇数时先手胜,是偶数时后手胜。

代码如下

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<map>
using namespace std;
int m;
int main(){
int T;
scanf("%d",&T);
for(int j=;j<=T;j++){
scanf("%d",&m);
int n=,x;
for(int i=;i<=m;i++){
scanf("%d",&x);
while(x){
n+=(x&);
x/=;
}
}n+=m;
printf("Case %d: ",j);
if(n&){
printf("Yes\n");
}
else{
printf("No\n");
}
}
return ;
}