hihocoder1172 : 博弈游戏·Nim游戏·二

Nim游戏

题目传送门

因为博主懒得打了,就把hihocoder上的思路直接Ctrl+C过来(其实上面写得很详细)

首先,我们先将局面分解一下,每一次我们只考虑一枚硬币。
不妨设所有硬币全部背面朝上的局面为局面0
假设现在N枚硬币,只有第1枚是正面朝上的。该局面只能转化为全部硬币背面朝上的局面。我们假定该局面为 局面1,则局面1可以转化为局面0。
假设只有第2枚是正面朝上的。该局面可以转化为:只有硬币1正面朝上;全部硬币背面朝上。我们假定该局面为 局面2,局面2可以转化为局面1和局面0。
同理我们可以推定,第i枚硬币正面朝上的局面为局面i,局面i可以转化为局面0..i-1。

现在,我们考虑把给定的局面拆成单个硬币的局面集合,比如给定了{HHTHTTHT},其中H表示正面朝上,T表示背面朝上。那么就是当前局面={局面1,局面2,局面4,局面7}。每一次我们可以改变其中个一个局面,当出现局面0时就从集合中删去。
这样一看是不是就变成了Nim游戏了?然而事实并没有那么简单。

进一步分析,若同时存在i,j(j < <script type="math/tex" id="MathJax-Element-60"><</script>i)两枚硬币正面朝上。我们将这个局面拆成2个单一的局面:即局面i和局面j。
在反转i的时候我们考虑从局面i转移到局面j,那么我们会有两个局面j。
表示第j枚被反转了2次,也就是回到了背面朝上的状态。
那么我们得到这个游戏一个性质:当出现两个同样的局面时,等价于这两个局面合并变成了局面0。

这种情况在Nim游戏中是没有的,那么它会对Nim游戏的状态造成影响么?
我们想一想,在Nim游戏中,如果出现两个数量相同的堆时,比如A[i]=A[j]。在计算Nim游戏状态时我们采用的xor操作,xor有交换律和结合律。则我们可以变成:
(A[i] xor A[j]) xor Other
因为A[i] = A[j],所以A[i] xor A[j] = 0。上式实际就是:
0 xor Other
也就是说在原Nim游戏中,若出现了两个数量相同的堆时,实际上这两堆已经不对总局面造成影响了,也就可以认为这两对合并为了一个数量为0的堆。

到此,我们可以发现这个硬币游戏完全满足Nim游戏的规则,其解答也满足Nim游戏的性质,这题也就很简单的转化为了普通的Nim游戏。

即实际上有H的个数堆石子,每对的个数为H所在原字符串的位置

然后和Nim游戏一样做就行了。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 10000
using namespace std;
int n,m;
char s[MAXN+5];
int a[MAXN+5];
int main(){
    scanf("%d",&n);
    scanf("%s",s);
    for (int i=0;i<n;i++)//转化
        if (s[i]=='H')
            a[++m]=i+1;
    int t=0;
    for (int i=1;i<=m;i++) t^=a[i];
    if (t==0) printf("Bob\n");
    else printf("Alice\n");
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值