Chess
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1908 Accepted Submission(s): 831
The first line contains an integer T(T≤100), indicates the number of test cases.
For each test case, the first line contains a single integer n(n≤1000), the number of lines of chessboard.
Then n lines, the first integer of ith line is m(m≤20), indicates the number of chesses on the ith line of the chessboard. Then m integers pj(1≤pj≤20)followed, the position of each chess.
題意:給n堆石子,有兩種操作,第一種是選擇任意一堆取走一些石子,可以取完這一堆,但不能不取。第二種操作是把某一堆分成三堆石子,每堆石子不能爲空。問先手是否必勝。
SG函數,因爲數據是1e9,所以打表找一下規律。
#include <bits/stdc++.h>
using namespace std;
int SG[1000];
int sg(int x)
{
if(SG[x] != -1) return SG[x];
int vis[150] = {0};
for(int i = 1;i <= x;i++) ///正常的nim取石子
vis[sg(x-i)] = 1;
for(int i = 1;i <= 100;i++){ ///採用另一種操作,分成三堆
for(int j = 1;j <= 100;j++){
for(int k = 1;k <= 100;k++){
if(i+j+k == x){
vis[sg(i)^sg(j)^sg(k)] = 1;
}
}
}
}
for(int i = 0;;i++)
if(!vis[i]) return SG[x] = i;
}
void Init()
{
memset(SG,-1,sizeof SG);
SG[0] = 0;
SG[1] = 1;
SG[2] = 2;
sg(100);
for(int i = 0;i <= 100;i++) printf("%d %d\n",i,SG[i]);
}
int SG_(int x)
{
if(x%8 == 7) return x+1;
if(x%8 == 0) return x-1;
return x;
}
int main()
{
//Init(); 打表找規律
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
int ans = 0;
for(int i = 1;i <= n;i++){
int t;
scanf("%d",&t);
ans ^= SG_(t);
}
if(ans) puts("First player wins.");
else puts("Second player wins.");
}
return 0;
}