Return of the Nim
发布时间: 2017年5月13日 22:40 最后更新: 2017年5月31日 20:20 时间限制: 1000ms 内存限制: 128M
Sherlock and Watson are playing the following modified version of Nimgame:
- There are n piles of stones denoted as , ,..., , and n is a prime number;
- Sherlock always plays first, and Watson and he move in alternating turns. During each turn, the current player must perform either of the following two kinds of moves:
- Choose one pile and remove k(k >0) stones from it;
- Remove k stones from all piles, where 1≤k≤the size of the smallest pile. This move becomes unavailable if any pile is empty.
- Each player moves optimally, meaning they will not make a move that causes them to lose if there are still any better or winning moves.
Giving the initial situation of each game, you are required to figureout who will be the winner
The first contains an integer, g, denoting the number of games. The 2×g subsequent lines describe each game over two lines:
1. The first line contains a prime integer, n, denoting the number of piles.
2. The second line contains n space-separated integers describing the respective values of 〖piles〗_0, 〖piles〗_1,..., 〖piles〗_(n-1).
1≤g≤15
2≤n≤30, where n is a prime.
1≤pilesi≤〖10〗^5 where 0≤i≤n−1
For each game, print the name of the winner on a new line (i.e., either “Sherlock” or “Watson”)
2 3 2 3 2 2 2 1
Sherlock Watson
操作1:从任意堆里拿任意个,
操作2:从所有堆里拿走x个,其中x不小于最小的那堆石子的个数
题目保证n是质数
结论:n=2时,巴什博奕
n>2时,尼姆博弈
n=2时,不用说,至于为什么n>2时是尼姆博弈,可以通过平衡状态来看,设平衡状态为所有石子数量值异或起来等于0,也就是先手必输状态
对于平衡状态,执行操作1后必然会破坏平衡状态,这是尼姆博弈,执行操作2也必然会破坏平衡状态 ,可以从二进制位考虑,因为无论拿走多少,必然会使他的某一位二进制位发生取反变化,而n是质数,且不为2,也就一定是奇数,
只考虑变化的那一位二进制位
平衡状态时只会是 奇数个0,偶数个1,(异或起来才会是0)
反转后变为偶数个0,奇数个1,异或起来则变成了1(其实n只要是奇数就满足,出题人心机了一波。。。。)
所以对于平衡状态,无论进行什么操作都会变成不平衡状态
而对于不平衡状态,都可以通过某一种操作1变成平衡状态
因此符合尼姆博弈条件
#include<bits/stdc++.h>
using namespace std;
double _=(sqrt(5)+1)/2.0;
double eps=1e-5;
int main()
{
int g,n,a[100],i;
cin>>g;
while(g--)
{
cin>>n;
for(i=0;i<n;i++)
cin>>a[i];
if(n==2)
{
int a1=min(a[0],a[1]);
int a2=max(a[0],a[1]);
if(floor((a2-a1)*_)==a1)
cout<<"Watson"<<endl;
else
cout<<"Sherlock"<<endl;
}
else
{
int ans=0;
for(i=0;i<n;i++)
ans^=a[i];
if(ans)
cout<<"Sherlock"<<endl;
else
cout<<"Watson"<<endl;
}
}
return 0;
}