SDNUOJ 1251.G.请回答Alice和Bob

sdnuoj1251题目链接

比赛的时候混淆了博弈论的规则,感觉这个题的规则不伦不类的,又像威佐夫博弈又像尼姆博弈的,没想到真的是这个样子,比赛的时候题目中第二个规则的最后一条没有看到,还有就是没有用到素数的提示,导致思路全无,后来自己想的时候,发现可以分开做,即n==2的时候就是威佐夫博弈,当n不等于二的时候,规则像极了尼姆博弈,于是就想,尼姆博弈面对奇异局势之时,即所有数异或结果为0时,此时先手之人必定不会只选择一堆(白白等死),他一定会尝试同时取多堆石子(万一有救呢对吧。。),于是问题来了,取多堆石子的目的是完成必败态到必败态的转变,能不能成功呢,没思路了
于是想看看有没有人写题解,百度了一下,发现这居然是第八届省赛的a题,师哥只是改了改主人公的名字而已。。。大佬找到了两个我没想到的地方

1.除2以外的素数都是奇数

2.必败态时每堆石子二进制对应位数必定是 奇数个0 + 偶数个1(不难发现其实)

这样在取石子的时候,必定会有所有石子某一位全部取反,取反之后该位对应着 奇数个1 + 偶数个0,异或结果必定非0,即无法实现由必败态到必败态的转变(还是要等死),而当奇数堆变为偶数堆的时候(某一堆取完),第二个条件的第二部分无法使用,总结一下就是普通又扯淡的尼姆博弈!!

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
using namespace std;
int a[35];
int main()
{
    int t;
    int n;
    scanf("%d",&t);
    while(t --)
    {
        scanf("%d",&n);
        int ans = 0;
        for(int i = 1; i <= n; i ++){
            scanf("%d",&a[i]);
            ans ^= a[i];
        }
        if(n == 2)//威佐夫博弈
        {
            double w = (sqrt(5) + 1) / 2;
            if(a[1] > a[2]) swap(a[1], a[2]);
            int k = w * (a[2] - a[1]);
            if(k == a[1]) printf("Bob\n");
            else printf("Alice\n");
        }
        else//尼姆博弈
        {
            //int ans = 0;
            if(ans) printf("Alice\n");
            else printf("Bob\n");
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值