题目链接:LA5059
【题意】:有n堆石子,第i堆石子有ai个,两个玩家依次轮流取石子,每次从一堆中最少取一个,不能超过该堆石子数量的一半(1<=取石子数<=ai/2);
【思路】:sg打表,发现所有偶数的sg值都为该数的1/2,奇数的sg值是当/2是遇到的第一个偶数的1/2.
【代码如下】
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
LL x;
int n,t;
int main(){
scanf("%d",&t);
while(t --){
scanf("%d",&n);
LL ans = 0;
for(int i = 0; i < n; i ++){
scanf("%lld",&x);
if(x % 2 == 0) ans ^= x/2;
else{
while(x % 2) x/=2;
ans ^= x/2;
}
}
if(ans) printf("YES\n");
else printf("NO\n");
}
return 0;
}
【打表代码如下】
#include <bits/stdc++.h>
using namespace std;
int sg[110];
int n;
int main(){
scanf("%d",&n);
sg[1] = 0;
for(int i = 2; i <= n; i ++){
set<int>st;
for(int j = 1; 2*j <= i; j ++) st.insert(sg[i - j]);
int res = 0;
while(st.count(res)) res ++;
sg[i] = res;
}
for(int i = 1; i <= n; i ++) printf("%d**%d\n",sg[i],i);
return 0;
}