石子游戏
Time Limit: 10 Sec Memory Limit: 256 MB
Description
Output
输出T行,表示每组的答案。
3
1
1
2
1
0 0
3
1 2 2
4 4 4 4
Sample Output
1
0
6
HINT
Solution
这显然是一道博弈论的题目。我们发现这是一个树结构,仔细看了一下,发现这显然是一个阶梯Nim的模型。
我们将所有和同n奇偶的值XOR起来就可以得到SG。我们先判断一下,若SG=0则显然必败,否则必胜。
然后我们开始计算方案,枚举每一个节点,目标显然就是要让SG=0。
由于XOR的消去率,根据题意,可以分 2 种情况分别讨论:(根据SG异或值判断是加入还是取出。)
1. 从父亲那加入值,显然就是需要 ( SG^a[这个点] ) - a[这个点的父亲] <= a[这个点],这样才可以通过加入若干个值使得SG=0;
2. 把值给儿子,显然需要 (SG^a[这个点]) <= a[这个点],这样才可以通过拿走若干的值使得SG=0。
然后我们讨论一下是否为叶子节点:
1. 非叶节点,若从父亲那加入值只有1的贡献,把值给儿子(由于有两个儿子)所以贡献为2;
2. 叶子节点,从父亲那加入值或者彻底删去都显然只有1的贡献。
这样就可以求出方案数了。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| #include<bits/stdc++.h> using namespace std;
const int ONE = 10001; const int INF = 214783640; const int MOD = 1e9+7;
int T; int n; int x,num; int a[17][65537]; int SG,Ans;
int get() { int res=1,Q=1; char c; while( (c=getchar())<48 || c>57) if(c=='-')Q=-1; if(Q) res=c-48; while((c=getchar())>=48 && c<=57) res=res*10+c-48; return res*Q; }
void Solve() { n=get(); SG=Ans=0; for(int i=1;i<=n;i++) for(int j=1;j<=(1<<(i-1));j++) { a[i][j]=get(); if(i%2==n%2) SG ^= a[i][j]; } if(!SG) {printf("0"); return;}
for(int i=1;i<=n;i++) { for(int j=1;j<=(1<<(i-1));j++) if(i%2==n%2) { if(i!=n) { if( (SG^a[i][j]) <= a[i][j]) Ans+=2; if( (SG^a[i][j]) > a[i][j] && (SG^a[i][j]) - a[i-1][(j-1)/2+1] <= a[i][j]) Ans+=1; } if(i==n) { if( (SG^a[i][j]) <= a[i][j] ) Ans++; if( (SG^a[i][j]) > a[i][j] && (SG^a[i][j]) - a[i-1][(j-1)/2+1] <= a[i][j] ) Ans++; } } }
printf("%d",Ans); }
int main() { T=get(); while(T--) Solve(),printf("\n"); }
|