SDUT 3893 (山东省第八届ACM省赛A题) Return of the Nim 博弈nim+威佐夫

来源:互联网 发布:头脑风暴软件 编辑:程序博客网 时间:2024/06/05 04:13

Return of the Nim

Time Limit: 1000MS Memory Limit: 65536KB

Problem Description

Sherlock and Watson are playing the following modified version of Nim game:

  • 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:
    1. Choose one pile and remove k(k >0) stones from it;
    2. Remove k stones from all piles, where 1≤kthe 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 figure out who will be the winner

Input

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,,...,.

  • 1≤g≤15
  • 2≤n≤30, where n is a prime.
  • 1≤pilesi where 0≤in−1

Output

For each game, print the name of the winner on a new line (i.e., either "Sherlock" or "Watson")

Example Input

232 3 222 1

Example Output

SherlockWatson

Hint

Author

“浪潮杯”山东省第八届ACM大学生程序设计竞赛(感谢青岛科技大学)


题目大意
夏洛克和华生在一起玩取石子游戏,游戏规则:有n堆石子,夏洛克先手,游戏中允许两种操作:1.从任意一堆中取出k个石子;2.从每堆石子中取出k个石子,有石子堆为空时,该操作不准。两人每次必须任选一项操作,最后取完者胜。

题目分析
这道题乍一看是威佐夫博奕,但是只有两堆石子时才能使用威佐夫博奕。当石子堆n>=3时,我们发现题目在尼姆博弈的基础上,添加了操作2。那么我们考虑,如果我遇到尼姆博奕的必败态,我能否通过操作2反败为胜呢?假设现在有三堆石子15,6,9。转化成二进制会更加直观
1 1 1 1
0 1 1 0
1 0 0 1
如果选择操作2,从每堆中取出m个石子,一定会使二进制的某一位异或为1,比如m=2,二进制的倒数第二位异或值为1。(并且值得注意的是,只有n为奇数时,该结论成立,题目要求n为素数,一定符合奇数)下一步,对方一定可以通过尼姆博奕的操作1,使局势重新回到我的必败态。
这样一来,操作2,对尼姆博奕就没有影响了,当n>=3时,就是24k纯尼姆博奕。


ac代码
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cmath>using namespace std;int a[1000];int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n;        scanf("%d",&n);        for(int i=0; i<n; i++)        {            scanf("%d",&a[i]);        }        if(n==2)//Wythoff威佐夫博弈        {            if(a[0]<a[1])            {                swap(a[0],a[1]);            }            if(floor((a[0]-a[1])*((sqrt(5.0)+1.0)/2.0))!=a[1])            {                printf("Sherlock\n");            }            else            {                printf("Watson\n");            }        }        else//nim博弈        {            int k=a[0];            for(int i=1; i<n; i++)            {                k^=a[i];            }            if(k==0)            {                printf("Watson\n");            }            else            {                printf("Sherlock\n");            }        }    }    return 0;}





阅读全文
0 0
原创粉丝点击