题目:hdu 5795
题意:给定几个堆,并告诉你每个堆的石头数量,每次可以取一堆中的任意数量不能不取,并且可以分成3堆,求最后的赢家
题解:由打表可知,sg[i]={i,i-1(i%8==0),i+1(i%8==7)},只要满足每堆sg 异或 和为0 就为必胜战略
打表:
#include<bits/stdc++.h>
#define N 225005
using namespace std;
int dp[10000000];
bool vis[1000000];
void getNim()
{
dp[0]=0;
dp[1]=1;
dp[2]=2;
for(int i=3;i<=100;i++)
{
memset(vis,0,sizeof(vis));
for(int j=1;j<i-1;j++)//分成三堆,异或和
{
for(int k=1;k<i-j;k++)
{
vis[dp[j]^dp[k]^dp[i-j-k]]=1;
}
}
for(int j=1;j<i;j++) vis[dp[j]]=1; //可以取任意数量 不能不取
for(int j=1;j<=1000000;j++) if(!vis[j]){dp[i]=j;break;}
}
for(int i=1;i<=100;i++) cout<<dp[i]<<" "<<i<<endl;
}
int main()
{
getNim();
}
代码:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cstdio>
using namespace std;
long long getSG(long long value)
{
if(value%8==7)
{
return value+1;
}
else if(value%8==0)
{
return value-1;
}
else
{
return value;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
long long value;
scanf("%d",&n);
long long ans=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&value);
ans^=getSG(value);
}
if(!ans)
{
printf("Second player wins.\n");
}
else
{
printf("First player wins.\n");
}
}
return 0;
}