hdu 4388 Stone Game II 博弈

版权声明:转载注明下出处就行了。 https://blog.csdn.net/LJD201724114126/article/details/82977541

题目链接:hdu 4388

参考博客:https://blog.csdn.net/y1196645376/article/details/52143551

题意:

最初有n堆石子,每堆石子个数已知。两人轮流执行操作,如果当某人无法执行有效操作时即输。

操作分两步:

    第一步为:选择其中一堆石子假定石子个数为a,拿走个数不为0的一些石子使得该堆石子剩余k个并且保证(0 < k < a,k^a < a),^为异或符号。

    第二步为:加入一堆新的石子,石子个数为k^a,当然你也可以使用技能使得加入的石子个数变为(2k)^a。不过每个人每局游戏只能使用一次技能。

无法执行有效操作即第一步或者第二步无法执行时。

题解:直接看代码,里面有很详细的注释。

///先看下题目要求,每次留下的k,满足 0<k<n && kXORn <n,
///这说明,k只能在n中取二进制位1的数位,例如n=5(101),那么k只能是4(100)或者1(001)
///还能知道堆数为2^i时(二进制只有一位1),不能再分了,已到达边界了。
///然后我们假设先考虑一堆石子(n=1),k为这堆石子二进制位为1的个数,假设为偶数,先手win,也就是n+k为奇数时,先手win
///接着我们考虑有多堆石子(n>1),sum为这堆石子二进制1的个数,类比于一堆石子,sum+n为奇数时先手win,多堆可以看做单堆单堆的取,
///对了,每位选手还有一次技能加成的机会,我们要清楚的一点的是,这次加成的是用在新加堆上的,并且也不会改变新加堆的二进制位为1的个数
///例如n=13(1101),留k=5(101),2*k=1010, k XOR n=1000 ,2*k XOR n=0111,可见,不管用不用技能,新加堆的二进制位为1的个数的奇偶数还是没变。over。

/*
例如
n=15(1111)

1 111 先手
1 100 11 后手
1 100 1 1 先手

*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>


using namespace std;

int main()
{

    int ncase;
    scanf("%d",&ncase);

    for(int T=1;T<=ncase;T++)
    {
        int n;
        scanf("%d",&n);

        int x,sum=0;

        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            sum+=__builtin_popcount(x); ///库函数查找x数字二进制为1的个数,
            ///这库函数有个小坑,前面的下横线要两条,艹。
        }

        if((sum+n)&1) printf("Case %d: Yes\n",T);
        else printf("Case %d: No\n",T);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/LJD201724114126/article/details/82977541