HDU4388:Stone Game II(博弈+思维)
Stone Game II
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 609 Accepted Submission(s): 350
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4388
Descripton:
Stone Game II comes. It needs two players to play this game. There are some piles of stones on the desk at the beginning. Two players move the stones in turn. At each step of the game the player should do the following operations.
First, choose a pile of stones. (We assume that the number of stones in this pile is n)
Second, take some stones from this pile. Assume the number of stones left in this pile is k. The player must ensure that 0 < k < n and (k XOR n) < n, otherwise he loses.
At last, add a new pile of size (k XOR n). Now the player can add a pile of size ((2*k) XOR n) instead of (k XOR n) (However, there is only one opportunity for each player in each game).
The first player who can't do these operations loses. Suppose two players will do their best in the game, you are asked to write a program to determine who will win the game.
Input:
The first line contains the number T of test cases (T<=150). The first line of each test cases contains an integer number n (n<=50), denoting the number of piles. The following n integers describe the number of stones in each pile at the beginning of the game.
You can assume that all the number of stones in each pile will not exceed 100,000.
Output:
For each test case, print the case number and the answer. if the first player will win the game print "Yes"(quotes for clarity) in a single line, otherwise print "No"(quotes for clarity).
Sample Input:
3 2 1 2 3 1 2 3 4 1 2 3 3
Sample Output:
Case 1: No Case 2: Yes Case 3: No
题意:
给出n堆石子,每堆石子都有一定的个数,然后现在两个人来取石子。假设当前这堆石子个数为n,那么最终他留下了k个石子,必须满足0<k<n且n^k<n。之后再加上一堆数量为n^k的石子。
每个人有一次机会,加上一堆个数为(2*k)^n的石子。最后问是否先手必赢。
题解:
由题意我们可以知道,最终经过一次拆分过后,会有两堆石子,一堆个数为k,另一堆个数为n^k,并且可以进一步推知,如果有一堆石子的个数刚好为2^x,那么此时就是不可再分了。
由于这里是多堆石子不好分析,我们可以先考虑石子只有一堆的情况,通过对拆分后两堆石子个数二进制的分析,我们可以知道,拆分后的两堆石子二进制中1的个数的奇偶性和原来那个堆二进制中1的个数是一致的。假设我们最后拆分为了m堆,已经到达不可再分的状态,此时操作了m-1次,现在假设n中二进制个数为x,那么这里x和m是同奇偶的,如果最后我们要得知谁赢,只需要知道操作次数的奇偶性就行了。而这里m比较难得到,但是k是很容易知道的,所以我们就通过对k-1的奇偶性的判断就可以知道操作次数的奇偶数,这个时候一堆石子的情况就比较显然了。
这里可能会有技能,就是多出来的那一堆的个数为(2*k)^n,但是这里我们其实可以知道这一堆1的奇偶性也并未改变。对于每一位分情况分析一下就行了。所以其实这个技能的存在并不影响我们的分析。
多堆石子的情况下,也是同样的道理,对奇偶性的情况进行分析了,把所有堆操作次数的奇偶性计算出来就行了。
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> using namespace std; typedef long long ll; const int N = 55; int T,n; int a[N]; int main(){ ios::sync_with_stdio(false);cin.tie(0); cin>>T; int Case = 0; while(T--){ Case++ ; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; int cnt = 0; for(int i=1;i<=n;i++){ for(int j=30;j>=0;j--) if(a[i]&(1<<j)) cnt++; } cout<<"Case "<<Case<<": "; if((cnt+n)&1) cout<<"Yes"<<'\n'; else cout<<"No"<<'\n'; } return 0; }
重要的是自信,一旦有了自信,人就会赢得一切。