HDU 3032 Nim or not Nim?

来源:互联网 发布:天龙八部辅助软件 编辑:程序博客网 时间:2024/05/28 23:09

Problem Description
Nim is a two-player mathematic game of strategy in which players take turns removing objects from distinct heaps. On each turn, a player must remove at least one object, and may remove any number of objects provided they all come from the same heap.

Nim is usually played as a misere game, in which the player to take the last object loses. Nim can also be played as a normal play game, which means that the person who makes the last move (i.e., who takes the last object) wins. This is called normal play because most games follow this convention, even though Nim usually does not.

Alice and Bob is tired of playing Nim under the standard rule, so they make a difference by also allowing the player to separate one of the heaps into two smaller ones. That is, each turn the player may either remove any number of objects from a heap or separate a heap into two smaller ones, and the one who takes the last object wins.

Input
Input contains multiple test cases. The first line is an integer 1 ≤ T ≤ 100, the number of test cases. Each case begins with an integer N, indicating the number of the heaps, the next line contains N integers s[0], s[1], …., s[N-1], representing heaps with s[0], s[1], …, s[N-1] objects respectively.(1 ≤ N ≤ 10^6, 1 ≤ S[i] ≤ 2^31 - 1)

Output
For each test case, output a line which contains either “Alice” or “Bob”, which is the winner of this game. Alice will play first. You may asume they never make mistakes.

Sample Input
2
3
2 2 3
2
3 3

Sample Output
Alice
Bob

Source
2009 Multi-University Training Contest 13 - Host by HIT

Recommend
gaojie | We have carefully selected several similar problems for you: 3031 3033 3038 3035 3034

题意:
给你n堆石子,Alice和Bob两个人进行博弈。他们每次可以选择拿走一堆之中的任意个石子(1~ALL)或者将其分成两堆((1,ALL-1),(2,ALL-2)…(ALL-1,1))都可以。Alice先手,求最后赢家。

每一堆石子都可以看做一个子游戏,也就是分治。就是对NIM的思维总结而成的sg函数。

SG函数:
游戏的和的SG函数值是它的所有子游戏的SG函数值的异或。
首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。例如mex{0,1,2,4}=3、mex{1,3,5}=0、mex{}=0。

mex表示 SG某一状态的后续状态。
更方便使用,我们就把这种状态看做场上剩余石子数。

比方说
SG(0)没有后续状态,mex是空集,集合中不包含的那么最小非负整数就是 0;
SG(1)后续状态有 0,mex为{0},集合中不包含的最小非负整数为1;
不过当然了= = 我这种菜鸡还是看不出来有什么规律的
还是打表吧= =

打表:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn=1e4+10;int sg[maxn],vis[maxn];void init(){    int i,j,k;    sg[0]=0,sg[1]=1;    for(i=2;i<=1000;i++)    {        memset(vis,0,sizeof(vis));        for(j=1;j<i;j++)        vis[sg[j]^sg[i-j]]=1;          for(j=0;j<i;j++)        vis[sg[j]]=1;                for(j=0;;j++)        if(!vis[j])break;        sg[i]=j;    }    for(i=1;i<=20;i++)    cout<<sg[i]<<endl;}int main(){    init();}

异或: 写作 1^1=0;1^0=1;
真⊕假=真
假⊕真=真
假⊕假=假
真⊕真=假
或者为:
True ⊕ False = True
False ⊕ True = True
False ⊕ False = False
True ⊕ True = False

#include<iostream>#include<cstring>#include<cmath>using namespace std;int t, n; int a[100005];void solve(){}int main(){    cin >> t;    while (t--)    {        cin >> n;        int ans = 0;        for (int i = 0; i < n; i++)        {            cin >> a[i];        }        for (int i = 0; i < n; i++)        {            if (a[i] % 4 == 1 || a[i] % 4 == 2)                ans ^= a[i];            else if (a[i] % 4 == 0)                ans ^= (a[i] - 1);            else                ans ^= (a[i] + 1);        }        if (ans)            cout << "Alice" << endl;        else            cout << "Bob" << endl;    }    return 0;}