Codeforces 768E:Game of Stones
题目链接:http://codeforces.com/contest/768/problem/E
题目大意:给定$n$堆石子,初始每堆$s_i$个石子.每次可从其中一堆中取任意$x(x leqslant s'_i)$个石子,每堆石子若之前取过$x$个则不能再取$x$个(可以取$x+t$个,其中$t eq 0$且$x+t leqslant s'_i$).若不能取石子则判定为输,问后手是赢还是输.
nim博弈
我们将整个博弈游戏看做由$n$个博弈游戏组成,考虑仅有一堆$s_i$个石子的情况。
设$sg[i]$为仅有一堆i个石子的胜利态级数,由于有不能取重复个数的条件限制,
故$sg[i+j]=max{sg[i]+1|j otin {a_k|i=sum_{k=1}^{sg[i]}a_k$,且$a_x eq a_y}$.
所以$sg[i]=p$,其中$p$为将$i$划分成若干个不同整数之和的划分数。
求出$sg[i]$后,将所有堆的胜利态级数异或后即得到总游戏的胜利态级数。
代码如下:
1 #include <iostream> 2 using namespace std; 3 int sg[65],k=1,n,t,ans; 4 int main(void){ 5 for(int i=1;i<=60;++i){ 6 if(i==(k+2)*(k+1)/2)k++; 7 sg[i]=k; 8 } 9 cin>>n; 10 while(n--){ 11 cin>>t; 12 ans^=sg[t]; 13 } 14 if(ans)cout<<"NO"; 15 else cout<<"YES"; 16 }