codeforces 768E Game of Stones

NIM游戏改版算法解析
本文介绍了一种NIM游戏变种问题的解决方案,针对每次取石子次数受限的情况,通过计算每堆石子对应的SG值并进行异或运算,判断游戏胜负。附带提供了一份实现该算法的C++代码。

题目链接:http://codeforces.com/problemset/problem/768/E


 

NIM游戏改版:对于任意一堆,拿掉某个次数最多只能一次。

对于一堆石头数量为$X$。找到一个最小的$Z$使得${ (\sum_{i=1}^{Z}i)\leq x}$,我们把这一堆数量为X的石头,看作Z个数目分别为${1...n}$的石头堆。

那么一次拿一定量的石头,是不是相当于拿走了${{1,2,3....,Z}}$中的任意多堆石头?

当然如果拿的石头数目$P$超过了${\sum _{i=1}^{Z}i}$,相当于拿走了所有大于${{Z}'}$的的石头堆。${{Z}'=Max\left \{ val|(\sum _{i=1}^{val}i)\leq (X-P) \right \}}$

所以${SG(X)=Max(Z|(\sum_{i=1}^{Z}i)\leq X)}$

很显然,这是一个multi-nim游戏,主游戏的SG值等于所有子游戏的异或和。


 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<cstring>
 8 using namespace std;
 9 #define maxn 10010
10 #define llg long long
11 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
12 llg n,m,x,v;
13 
14 llg make_sg(llg x)
15 {
16     if (x==0) return 0;
17     llg l=0,r=(llg)1e9,val;
18     while (l<=r)
19     {
20         llg mid=(l+r)>>1;
21         if ((mid*mid+mid)/2<=x) {l=mid+1; val=mid;}else r=mid-1;
22     }
23     return val;
24 }
25 
26 int main()
27 {
28     yyj("SG");
29     cin>>n;
30     
31     for (llg i=1;i<=n;i++)
32     {
33         scanf("%lld",&v);
34         x^=make_sg(v);
35     }
36     if (!x) cout<<"YES";else cout<<"NO";
37     return 0;
38 }

 

转载于:https://www.cnblogs.com/Dragon-Light/p/6423316.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值