HDU-3032Nim or not Nim?(SG打表)

题目传送门

Nim or not Nim?

题目大意

Alice和Bob做游戏,共有n堆石子,没堆石子为 s [ i ] s[i] s[i]个,每一次可以从任意一堆中拿走任意个石子,也可以将一堆石子分为两个小堆。先拿完者获胜。
Alice先手

思路

用SG打表后在这里插入图片描述
发现规律是
x = x − 1   w h e n   ( x % 4 = = 0 ) x=x-1\ when\ (x\%4==0) x=x1 when (x%4==0)
x = x + 1   w h e n   ( x % 4 = = 3 ) x=x+1\ when\ (x\%4==3) x=x+1 when (x%4==3)
在用SG打表时,注意操作将一堆分成两堆即为枚举分成两堆的情况
最后用得到的规律算出每堆的值求异或即可

AC Code

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<math.h>
using namespace std;
#define endl '\n'
#define INF 0x3f3f3f3f
// #define int long long
#define debug(a) cout<<#a<<"="<<a<<endl;
typedef long long ll;
const double PI=acos(-1.0);
const double e=exp(1.0);
const int M=1e9+7;
const int N=105;
inline int mymax(int x,int y){return x>y?x:y;}
inline int mymin(int x,int y){return x<y?x:y;}
int vis[N], sg[N];
void init(int n) {
    sg[0]=0;sg[1]=1;
	for (int i = 2; i <= n; i++) {
		memset(vis, 0, sizeof(vis));
		for (int j = 0; j <= i; j++) vis[sg[i - j]] = true;
		for (int j = 0; j <= i; j++) vis[sg[j] ^ sg[i - j]] = true;
		int j=0;
        while(vis[j]!=0) j++;
        sg[i]=j;
	}
	for (int i = 1; i < n; i++){
        cout<<sg[i]<<" ";
        if(i%4==0) cout<<endl;
    }
}
int n, x;
void solve(){
    cin>>n;
    int ans=0;
    for(int i=1; i<=n; ++i){
        cin>>x;
        if(x%4==0) --x;
        else if(x%4==3) ++x;
        ans^=x;
    }
    if(ans==0)  cout<<"Bob"<<endl;
    else        cout<<"Alice"<<endl;
}

signed main(){
    // init(N);
    int T;cin>>T;
    while(T--) solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值