「反Nim」数列游戏

本题为12月27日22寒假集训每日一题题解

题目来源:(未知)

题面

题目描述

cad和jyx最近迷上了一款名为插入数列的游戏,有一个n行m列的网格,你每次可以按下1个或多个格子,但必须要在同一列且连续,已经按过的地方不可以再按,谁按下最后一个格子,谁就输了,刚开始的时候互有胜负,但玩过几把之后两个人慢慢的就知道了自己最优的走法是什么,现在问题来了,给你n和m你能告诉我谁会赢吗?(cad先手)

输入

多组测试样例

每组测试样例两个数分别表示行和列(n,m<=1e5)

输出

输出赢的人的名字

样例输入

1 1

样例输出

jyx


思路分析

显然,这是一个反Nim问题,列为堆,行为堆里元素的个数,直接套用反Nim问题的结论即可.

反Nim问题的结论:

当至少一堆大于1时,与Nim问题一致 异或和为0,必败;异或和不为0,必胜

当每一堆都是1时,与Nim问题相反 异或和不为0,必败;异或和为0,必胜

不过由于这里每一堆里元素的个数都是相同的,所以异或和可以直接用行的奇偶性代替(奇即异或和非0,偶即异或和为0).

参考代码

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3, "Ofast", "inline")

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
    ios::sync_with_stdio(false);

    // 输入数据
    int n, m;
    while(cin >> n >> m)
    {
        // 反Nim问题的特殊情况
        if(n == 1)
        {
            m += 1; // +1使得奇偶性发生颠倒,即对Nim问题结论取反
        }

        // Nim问题结论
        if(m % 2)
        {
            cout << "cad\n";
        }
        else
        {
            cout << "jyx\n";
        }
    }

    return 0;
}

“正是我们每天反复做的事情,最终造就了我们,优秀不是一种行为,而是一种习惯” —亚里士多德