博弈,异或 1451F Nullify The Matrix

1451FThe (博弈 , 异或)
Round #685 (Div. 2)
F.The
题面: The
题意:一个n ? m n * m n?m 的矩阵m a t mat mat , 元素均为非负数 , 其上 (先手) 与 Jeel 玩一个游戏 。
每个人轮流操作的规则:
① 选择起点S ( r 1 , c 1 ) S(r1, c1) S(r1,c1) , 该点元素不能为0 0 0 。
【博弈,异或1451F Nullify The Matrix】② 选择终点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 r2≥r1,c2≥c1 。
③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 1≤n,m≤100,0≤mati,j?≤106 。
分析:
通过分析可以发现起点是最重要的 , 如果非0 0 0 点按照下图的对角线分布的话 , 每次最多只能让一个格子变成0 0 0 , 本质上与 Nim 取石子是一致的 , 只有当 异或值不等于0 时 , 局面必胜 , 因为先手总是可以变换成 异或值等于0 的局面留给对面 , 而最终的败态同样为 异或值等于0 。
因此通过按照对角线分割的方式我们可以将该游戏划分成r + c ? 1 r + c-1 r+c?1 个子游戏 , 但是本题中他们不是相互独立的 。
而题目提供的修改操作是在起点到终点的最短路上进行的 , 我们可以在路上进行任意赋值 , 意味着我们可以对其间的所有子游戏进行胜负态变换 , 以此来完成整体的胜负态变换 。
因此操作允许我们将当前的局面S S S:存在子游戏异或和非0 进行一次移动后变成局面S ′ S' S′:所有子游戏异或和均为0 , 并且局面S ′ S' S′ 进行一次移动必然会变换为局面S S S , 且最终败态为S ′ S' S′ , 因此根据起始局面是否为S S S 即可判断胜负态 。
Code:
#include #define int long long#define double long doubleusing 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】感谢观看