sdut 2161 Simple Game(山东省第二届acm省赛A题)(博弈论Nim+Bush?)

Simple Game

Time Limit: 1000MS Memory Limit: 65536KB

Problem Description

Here is a simple game. In this game, there are several piles of stones and two players. The two players play in turn. In each turn, one can choose at least one pile and at most three piles to take away arbitrary number of stones from the pile (Of course the number of stones, which is taken away, cannot be zero and cannot be larger than the number of stones in the chosen pile). If after a player ′ s turn, there is no stone left, the player is the loser.
Suppose that the two players are all very smart. Your job is to tell whether the player who plays first can win the game or not.

Input

The input has multiple test cases. The first line of the input contains one integer C, which is the number of test cases. Each test case begins with a line contains one integer N(1 <= N <=10000),which is the number of piles. Then comes N positive integers, which are not larger than 10000000. These N integers represent the number of stones in each pile.

Output

For each test case, output “Yes” in a single line, if the player who play first will win, otherwise output “No”.

Example Input

2
2
1
1
4
2
2
2
2

Example Output

Yes
No

Author

山东省第二届ACM大学生程序设计竞赛

题意

一共有n堆石子,n堆石子的数量均不相同,两个人从这n堆中取石子 每次最少取一个石子最多取三堆石子(也就是说可以选择三堆然后从中取任意个,但是最少要从其中一堆中取走一个),取走最后一枚石子的人获胜,然后告诉你有n堆石子和每堆石子的数量,问先手是否是必胜

思路

这道题与经典的Nim博弈不同的是,经典Nim中每个人只能选一堆石子,然后从中拿任意个,而此题为每个人最多从三堆石子中拿任意个(其实往后从多少堆里取都一样了),想想经典的Nim中 只要确保异或为1就好了 也就是说把每一堆石子的数量转化为二进制的话,如果二进制的每一位1的个数都为偶数个的话即为必败态(详情查阅Nim博弈)
现在在经典Nim博弈上变为最多取3堆,以相同的思路来解,如果二进制的每一位1的数量都为4的话,即为必败态,举个例子,设有5堆石子 石子的个数为7 13 11 14 15 则每个数字的二进制表示就如下表(反着的二进制)
sdut 2161 Simple Game(山东省第二届acm省赛A题)(博弈论Nim+Bush?)_第1张图片
由上图可以看出来,每一个二进制位都由4个1组成,所以假设你取走第一位(最低位)的三个1,则我可以取走剩下的那一个,假设给的数最低位有120个1,最后的那个1也一定是我拿(如果这个想不明白去看看Bash博弈) 每一位都是如此,最后则一定是后手取走最后一块石头,即先手必败,由此题便很容易的就解出来了

AC代码

#include 
#include 
using namespace std;
int bin[20];//算了一下最大的情况应该12位就够了?
int main() {
    int c,n,a;
    bool flag;
    cin>>c;
    while(c--) {
        memset(bin,0,sizeof(bin));
        cin>>n;
        while(n--) {
            cin>>a;
            for(int i=0; a; i++) {
                bin[i] += a%2;
                a/=2;
            }
        }
        flag = true;
        for(int i=0; i<20; i++) {
            if(bin[i]%4!=0) {
                flag = false;
                break;
            }
        }
        if(!flag) cout<<"Yes"<else cout<<"No"<return 0;
}



你可能感兴趣的:(acm省赛)