Codeforces 768E:Game of Stones

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 \neq 0$且$x+t \leqslant s'_i$).若不能取石子则判定为输,问后手是赢还是输.

nim博弈

我们将整个博弈游戏看做由$n$个博弈游戏组成,考虑仅有一堆$s_i$个石子的情况。

设$sg[i]$为仅有一堆i个石子的胜利态级数,由于有不能取重复个数的条件限制,

故$sg[i+j]=max\{sg[i]+1|j \notin \{a_k|i=sum_{k=1}^{sg[i]}a_k$,且$a_x \neq 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 }

 

posted @ 2017-02-23 14:15  barriery  阅读(442)  评论(0编辑  收藏  举报