HDU 4388 Stone Game II 博弈论 找规律

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是奇数时先手胜,是偶数时后手胜。

代码如下

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<map>
 7 using namespace std;
 8 int m;
 9 int main(){
10     int T;
11     scanf("%d",&T);
12     for(int j=1;j<=T;j++){
13         scanf("%d",&m);
14         int n=0,x;
15         for(int i=1;i<=m;i++){
16             scanf("%d",&x);
17             while(x){
18                 n+=(x&1);
19                 x/=2;
20             }
21         }n+=m;
22         printf("Case %d: ",j);
23         if(n&1){
24             printf("Yes\n");
25         }
26         else{
27             printf("No\n");
28         }
29     }
30     return 0;
31 }
View Code

 

posted @ 2017-12-18 11:31  鲸头鹳  阅读(232)  评论(0编辑  收藏  举报