题目大意:
共有n个瓶子,第i个瓶子中装有p[i]颗巧克力豆,两个人轮流取豆子,每一轮每人选择3个瓶子。标号i,j,k.并要保证i<j<=k且第i个瓶子中至少要有1颗巧克力豆,随后这个人从第i个瓶子中拿走一颗豆子并在j,k中各放入一粒豆子(j可能等于k)。如果轮到某人而他无法按规则取豆子,那么他将输掉比赛。你先取,求在给定每个瓶子中的最初豆子数后是否必胜,且求出第一步该如何取,第一步有多少种必胜取法?
sg题,此题注意每一颗豆子都是一个游戏,对每个豆子求sg.
代码如下:
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 const int N = 25;const int M = 10005; 5 int n,cnt,ans,f[N],a[N];bool b[M]; 6 int sg(int x) 7 { 8 if(x == n)return 0; 9 if(f[x] != -1)return f[x]; 10 memset(b,0,sizeof(b)); 11 for(int j = x + 1;j <= n;j++) for(int k = j;k <= n;k++) b[sg(j) ^ sg(k)] = 1; 12 int ret;for(ret = 0;b[ret];ret++);return f[x] = ret; 13 } 14 int main() 15 { 16 int T;scanf("%d",&T); 17 while(T--) 18 { 19 scanf("%d",&n);ans = cnt = 0; 20 memset(f,-1,sizeof(f)); 21 for(int i = 1;i <= n;i++) 22 { 23 scanf("%d",&a[i]); 24 if(a[i] & 1) ans ^= sg(i); 25 } 26 for(int i = 1;i < n;i++) 27 for(int j = i + 1;j <= n;j++) 28 for(int k = j;k <= n;k++) 29 if(!(ans ^ sg(i) ^ sg(j) ^ sg(k))) 30 if((++cnt) == 1) {printf("%d %d %d\n",i - 1,j - 1,k - 1);} 31 if(!cnt) puts("-1 -1 -1");printf("%d\n",cnt); 32 } 33 return 0; 34 }
时间: 2024-11-02 19:30:02