https://vjudge.net/problem/UVALive-7278
题意:
两个人玩游戏,现在有n堆牌,轮到自己时,先在牌堆中选一堆牌,先在牌堆中选择拿走0~k张牌(至少得剩下一张),然后最上面的那张牌的点数是多少,你就还需要在该牌堆拿走多少张牌。
不能拿者输。
思路:
虽然有多堆牌,但是我们可以一堆一堆分析。
用SG函数计算出每一堆的情况,最后异或和即可。
1 #include<iostream> 2 #include<string> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<cstdio> 7 using namespace std; 8 9 const int maxn=1000+5; 10 11 int n,p,k; 12 int a[maxn]; 13 int SG[maxn]; 14 int vis[maxn]; 15 16 int main() 17 { 18 //freopen("D:\input.txt", "r", stdin); 19 while(~scanf("%d%d",&p,&k)) 20 { 21 int pre=0; 22 for(int kase=0;kase<p;kase++) 23 { 24 memset(SG,0,sizeof(SG)); 25 scanf("%d",&n); 26 for(int i=1;i<=n;i++) 27 scanf("%d",&a[i]); 28 if(a[1]==1) SG[1]=1; 29 else SG[1]=0; 30 31 for(int i=2;i<=n;i++) 32 { 33 memset(vis,0,sizeof(vis)); 34 for(int j=0;j<=k && i-j>0;j++) 35 { 36 if(i-j-a[i-j]>=0) 37 vis[SG[i-j-a[i-j]]]=1; 38 } 39 for(int j=0;;j++) 40 { 41 if(!vis[j]) 42 { 43 SG[i]=j; 44 break; 45 } 46 } 47 } 48 pre^=SG[n]; 49 } 50 if(pre) puts("Alice can win."); 51 else puts("Bob will win."); 52 } 53 return 0; 54 }