您的位置:首页 > 编程语言

[QSCOJ39]喵哈哈村的代码传说 第五章 找规律

2017-09-29 15:32 260 查看

题目大意:
  给你n堆排,两人轮流对其中一堆牌进行以下操作之一:
    1.从这堆牌中取出任意数量的牌;
    2.将这这堆牌分为任意大小的3堆牌。
  不能操作者负。
  问先手是否有必胜策略。

思路:
  尝试构造sg函数,游戏的状态为某堆牌中牌的数量,
  打表计算发现当x为8的倍数时,sg(x)=x-1;
  当x在模8意义下为7时,sg(x)=x+1;
  否则sg(x)=x。
  手算了以下x=0~8时的情况,解释如下:
  当x=0时,先手没法操作,sg(x)=0;
  当x=1时,当前的后继状态为(0),sg(x)=mex{sg(0)}=1;
  当x=2时,当前的后继状态为(0)(1),sg(x)=mex{sg(0),sg(1)}=2;
  当x=3时,当前的后继状态为(0)(1)(2)(1 1 1),sg(x)=mex{sg(0),sg(1),sg(2),...,sg(1)^sg(1)^sg(1)}=3;
  ……
  当x=7时,当前的后继状态为(0)~(6)(1 1 5)(1 2 4)(1 3 5)(2 2 3),此时(1 2 4)所对应的sg值为sg(1)^sg(2)^sg(4),sg(7)=8;
  而当x=8时,当前的后继状态中(7)的sg值为8,而其它的后继状态中sg值也没有等于7的,所以sg(x)=7。
  程序实现十分简单。

#include<cstdio>
#include<cctype>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
inline int getsg(const int &x) {
if(x%8==0) return x-1;
if(x%8==7) return x+1;
return x;
}
int main() {
for(register int T=getint();T;T--) {
int ans=0;
for(register int n=getint();n;n--) {
ans^=getsg(getint());
}
puts(ans?"First player wins.":"Second player wins.");
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: