1451F Nullify The Matrix(博弈,异或)

1451F Nullify The Matrix(博弈,异或)

Codeforces Round #685 (Div. 2)

F. Nullify The Matrix

题面Nullify The Matrix

题意:一个 n ∗ m n * m nm 的矩阵 m a t mat mat,元素均为非负数,其上 Ashish(先手) 与 Jeel 玩一个游戏。

每个人轮流操作的规则:

① 选择起点 S ( r 1 , c 1 ) S(r1, c1) S(r1,c1),该点元素不能为 0 0 0

② 选择终点 T ( r 2 , c 2 ) T(r2, c2) T(r2,c2),满足 r 2 ≥ r 1 , c 2 ≥ c 1 r2 \ge r1, c2 \ge c1 r2r1,c2c1

S S S 点的值减少一个任意值 x ∈ [ 1 , m a t c 1 , r 1 ] x \in [1, mat_{c1, r1}] x[1,matc1,r1]

S S S T T T 的任意一条最短路,该路上的所有点(除了 S S S)赋予任意值。

无法操作者败,给定初始局面,问胜者是谁。

范围 1 ≤ n , m ≤ 100 ,   0 ≤ m a t i , j ≤ 1 0 6 1 \le n,m \le 100,~0 \le mat_{i,j} \le 10^6 1n,m100, 0mati,j106

分析

通过分析可以发现起点是最重要的,如果非 0 0 0 点按照下图的对角线分布的话,每次最多只能让一个格子变成 0 0 0,本质上与 Nim 取石子是一致的,只有当 异或值不等于0 时,局面必胜,因为先手总是可以变换成 异或值等于0 的局面留给对面,而最终的败态同样为 异或值等于0

在这里插入图片描述

因此通过按照对角线分割的方式我们可以将该游戏划分成 r + c − 1 r + c-1 r+c1 个子游戏,但是本题中他们不是相互独立的。

在这里插入图片描述

而题目提供的修改操作是在起点到终点的最短路上进行的,我们可以在路上进行任意赋值,意味着我们可以对其间的所有子游戏进行胜负态变换,以此来完成整体的胜负态变换。

因此操作允许我们将当前的局面 S S S存在子游戏异或和非0 进行一次移动后变成局面 S ′ S' S所有子游戏异或和均为0,并且局面 S ′ S' S 进行一次移动必然会变换为局面 S S S,且最终败态为 S ′ S' S,因此根据起始局面是否为 S S S 即可判断胜负态。

Code

#include <bits/stdc++.h>
#define int long long
#define double long double
using namespace std;
 
inline int read()
{
    int s = 0, w = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        s = s * 10 + ch - '0', ch = getchar();
    return s * w;
}
 
const int MAXN = 100 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double eps = 1e-9;
const double PI = acos(-1.0);
 
int n, m, k;
 
int arr[MAXN][MAXN];
 
int xorsum[MAXN * 2];

signed main()
{
    int T = read();
    while (T--)
    {
        memset(xorsum, 0, sizeof(xorsum));
        n = read(), m = read();
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                arr[i][j] = read();
                xorsum[i + j] ^= arr[i][j];
            }
        }
        int ans = 0;
        for (int i = 0; i < n + m; i++)
        {
            if (xorsum[i])
            {
                ans = 1;
                break;
            }
        }
        if (ans)
        {
            cout << "Ashish" << endl;
        }
        else
        {
            cout << "Jeel" << endl;
        }
    }
    return 0;
}

【END】感谢观看

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值