题意:有N堆石子,每堆有s[i]个,Alice和Bob两人轮流取石子,可以从一堆中取任意多的石子,也可以把一堆石子分成两小堆
Alice先取,问谁能获胜
思路:首先观察这道题的数据范围 1 ≤ N ≤ 10^6, 1 ≤ 【Si】 ≤ 2^31 - 1,很明显数据量太大,所以只能通过打表找规律
打表后发现,如果x%4==0 sg[x]=x-1 ;如果 x%4==3 sg[x]=x+1;如果 其他情况 sg[x]=x;
代码:
打表代码:
#include <iostream> #include <cstring> using namespace std; int sg[1000]; int get(int n) { if(n<0) return 0; if(sg[n]!=-1) return sg[n]; bool visit[1005]; memset(visit,false,sizeof(visit)); for(int i=1;i<=n/2;i++) visit[get(i)^get(n-i)]=true; for(int i=1;i<=n;i++) { visit[get(n-i)]=true; } int k; for(int i=0;i<=1000;i++) { if(visit[i]==false) { return sg[n]=i; } } } int main() { memset(sg,-1,sizeof(sg)); sg[0]=0;sg[1]=1; for(int i=2;i<=100;i++) { get(i); } for(int i=1;i<=100;i++) cout<<i<<" "<<sg[i]<<endl; return 0; }
AC代码:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int main() { int t; cin>>t; while(t--) { int n,x,ans=0; cin>>n; for(int i=1;i<=n;i++) { scanf("%d",&x); if(x%4==0) ans=ans^(x-1); else if(x%4==3) ans=ans^(x+1); else ans=ans^x; } if(ans) cout<<"Alice"<<endl; else cout<<"Bob"<<endl; } return 0; }