2020 Multi-University Training Contest 10 hdu6886 Tic-Tac-Toe-Nim(思维题 nim博弈)

题目

T(T<=5e5)组样例,

Alice和Bob在一个3*3的方格上玩取石子,9个格子每个格子对应一堆石子,

第i行第j列现有石子数为aij(1<=aij<=1e9),

Alice先手,Alice第一步必须将一堆石子全取走,Bob第一步也必须将一堆石子全取走,

之后的操作中,Alice和Bob正常像Nim一样取石子,

如果X取完石子后,出现了同一行三堆都没有石子或同一列三堆都没有石子的局面,则X胜

问Alice第一步有多少种选堆策略,可以保证后续必胜

思路来源

官方题解

题解

赛中没看到两人第一步都要全取

由于题目的nim性质,可以行与行、列与列互换,不影响答案,

不妨设Alice第一步完全取走(1,1),

这样,Bob第一步就不能与之同行同列,只能在(2,2)(2,3)(3,2)(3,3)里取,

不妨设Bob第一步完全取走(2,2),

这样在后续的操作中,对于(1,2)(1,3)(2,1)(2,3)(3,1)(3,2),两人谁先取到这六堆的最后一颗石子谁输

即对这6堆,每一堆减去一颗石子后,再考虑上(3,3)这一堆,

七堆石子谁先取完谁获胜,因为另一方只能被迫去取六堆的最后一颗石子,

 

如果对于Alice的(1,1),Bob(2,2)(2,3)(3,2)(3,3)四种局面都是Bob负,则Alice必胜,

统计个数即可,代码统计的是Alice不能必胜的堆数non

由于T=5e5,所以要枚举的精准一点,不能9*9*9的for

代码

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
#define fi first
#define se second
typedef unsigned long long ull;
int t,a[4][4],c,non;
P now[15];
int main(){
    scanf("%d",&t);
    while(t--){
        non=0;
        c=0;
        for(int i=1;i<=3;++i){
            for(int j=1;j<=3;++j){
                scanf("%d",&a[i][j]);
                now[++c]=P(i,j);
            }
        }
        for(int i=1;i<=c;++i){
            for(int j=1;j<=c;++j){
                if(i==j)continue;
                if(now[i].fi==now[j].fi || now[i].se==now[j].se)continue;
                int nim=0;
                for(int k=1;k<=3;++k){
                    for(int l=1;l<=3;++l){
                        if(P(k,l)==now[i] || P(k,l)==now[j])continue;
                        if(k==now[i].fi || k==now[j].fi || l==now[i].se || l==now[j].se){
                            nim^=(a[k][l]-1);
                        }
                        else{
                            nim^=a[k][l];
                        }
                    }
                }
                //printf("(%d,%d) (%d,%d) nim:%d\n",now[i].fi,now[i].se,now[j].fi,now[j].se,nim);
                if(nim==0){
                    non++;
                    break;
                }
            }
        }
        printf("%d\n",9-non);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小衣同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值