杭电多校第10场 6886 Tic-Tac-Toe-Nim(NIM博弈)

Problem Description
Alice and Bob are playing a new game that is a mixture of tic-tac-toe and nim.

There are 9 piles of stones forming a 3∗3 grid. Players take turns to remove the stones: in each turn, the player choose a remaining pile and remove a positive number of stones from it. Alice goes first. The first player to remove a pile so that a new empty row or column is formed wins. Notice that player does NOT have to be the one to remove all three piles to win, and diagonals does NOT count as a win.

However, to speed up the game, both players have decided they will always remove the whole pile they choose in their respective first turn, instead of removing only part of the pile. Now Alice wants to know how many different moves can she choose in the first turn so that she can still ensure her victory.

Input
The first line contains one integer T (1≤T≤500000), the number of test cases.
For each test case, there are 3 lines, each contains 3 integers aij (1≤aij≤109), denoting the number of stones in each pile.

Output
For each test case, output one integer denoting the answer. Output 0 when Alice can not win in the situation.

Sample Input
2
1 1 1
1 1 1
1 1 1
1 2 3
4 5 6
7 8 9

Sample Output
9
7

题意:
井字棋,A B轮流取,可以取一个格子里的一些石子,先取完一行或者一列获胜。
要求A B第一次取的时候必须取完一个格子。
求A是否必胜。

思路:
A取完一个格子后,有4个格子和它同行同列,如果B取了这几个中的一种,那么下次A再取完一个格子就赢了,所以B一定不会取和A同行同列的格子。

所以AB取了不同行不同列的两个格子,此时6个格子和A,B之前取的同行同列,1个格子和AB之前取的不同行不同列。

只要谁先取完了和A,B开头取的同行同列6个格子中的一个,谁就输了。

所以必败态是6个同行同列的格子为1,剩下一个不同行不同列的格子为0,这就是裸的nim博弈了。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;
const int maxn = 5005;
const int mod = 1e9 + 7;

int a[35][35];

int main() {
    int T;scanf("%d",&T);
    while(T--) {
        int Xor = 0;
        for(int i = 1;i <= 3;i++) {
            for(int j = 1;j <= 3;j++) {
                scanf("%d",&a[i][j]);
                Xor ^= (a[i][j] - 1);
            }
        }
        
        int ans = 0;
        for(int i = 1;i <= 3;i++) {
            for(int j = 1;j <= 3;j++) {
                int flag = 1;
                for(int ci = 1;ci <= 3;ci++) {
                    if(ci == i) continue;
                    for(int cj = 1;cj <= 3;cj++) {
                        if(cj == j) continue;
                        int num = Xor ^ (a[i][j] - 1) ^ (a[ci][cj] - 1) ^ (a[6 - i - ci][6 - j - cj] - 1) ^ (a[6 - i - ci][6 - j - cj]);
                        flag &= (num != 0);
                    }
                }
                ans += flag;
            }
        }
        printf("%d\n",ans);
        
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值