嘘~ 正在从服务器偷取页面 . . .

CF1451F Nullify The Matrix 题解


CF1451F Nullify The Matrix 题解

题目链接:Nullify The Matrix

题意

Ashish 和 Jeel 在玩游戏,有一个 $n\times m$ 的棋盘,每个格子有一个非负整数的权值。

两个人轮流操作,每次操作先选择一个权值非 $0$ 的格子作为起点,然后选择起点右下角的一个格子作为终点,然后选择它们之间的一条最短路径,然后给起点的权值减一个正整数、路径上每个点的权值随意加减(也可以不改变),但是都不能改成负数。

不能操作(全变成 $0$)就输了,Ashish 先手,问谁必胜。

这道题的思路和 CF1149E 挺像的。

记 $f_i = \bigoplus_{x+y=p}a_{x,y}$ ,那么先手必败当且仅当 $\forall i$ 有 $f_i = 0$ ;否则先手必胜。

证明 记 $\rm N$ 为先手必胜态,$\rm P$ 为先手必败态。

考虑证明在此最优策略下原问题转化一个有向图游戏。

  • 终止状态,显然为 $\rm P$ 。

  • 对于 $\rm P$ 态,即 $\forall i, f_i = 0$ 时,任意修改都会导致某个 $f_i\ne 0$ 。那么 $\rm P$ 的后继均为 $\rm N$ 。

  • 对于 $\rm N$ 态,即 $\exists i, f_i \ne 0$ 时,我们找到最小的 $i$ ,它对应第 $i$ 个斜线

    取这个斜线二进制最高位所在的那个 $a_{x,y}$ 为起点,然后类似于那道题一路改过去就好了。$\square$

时间复杂度 $\mathcal{O}(n^2)$

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x, int y) { x < y ? x = y : 0; }
void down(int &x, int y) { x > y ? x = y : 0; }
#define rep(i, a, b) for(int i = (a), i##END = (b); i <= i##END; i++)
#define Rep(i, a, b) for(int i = (a), i##END = (b); i >= i##END; i--)
#define N ((int)(233))

int a[N];
void solve()
{
    memset(a, 0, sizeof(a)); int n, m; cin >> n >> m;
    rep(i, 1, n) rep(j, 1, m) { int x; cin >> x; a[i + j] ^= x; }
    rep(i, 2, n + m) if(a[i]) return cout << "Ashish\n", void(0);
    cout << "Jeel" << '\n';
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    int qwq; cin >> qwq; while(qwq--) solve();
    return 0;
}

参考文献

[1] https://www.luogu.com.cn/article/2cnf2wjz


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录