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 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 }
原文地址:https://www.cnblogs.com/barrier/p/6433245.html