C++ 数论相关题目 博弈论 Nim游戏

给定 n
堆石子,两位玩家轮流操作,每次操作可以从任意一堆石子中拿走任意数量的石子(可以拿完,但不能不拿),最后无法进行操作的人视为失败。

问如果两人都采用最优策略,先手是否必胜。

输入格式
第一行包含整数 n

第二行包含 n
个数字,其中第 i
个数字表示第 i
堆石子的数量。

输出格式
如果先手方必胜,则输出 Yes。

否则,输出 No。

数据范围
1≤n≤105
,
1≤每堆石子数≤109
输入样例:
2
2 3
输出样例:
Yes

先手必胜状态:可以走到某一个必败状态
先手必败状态:走不到任何一个必败状态

几种状态:
(1)全部是0,异或起来也是0。(必败态
(2)异或起来不是0,若等于x,x的第k位为1的话,则一定存在一个ai的第k位等于1,则从ai中拿走ai-ai^x个石子,则剩下的异或为0。(证明:总存在一种拿法,使得拿完异或起来为0)
(3)异或起来是0,假设从ai中拿走一些,则剩下的异或起来一定不等于0,因为反正假设等于0,拿走前后的全部堆异起来有ai等于拿走部分后的ai,矛盾。
C++ 数论相关题目 博弈论 Nim游戏_第1张图片
总结:刚拿到石子,异或起来为不为0,则一定存在某种取法,使得剩下的异或为0,后手任意操作后状态一定不为0,这样循环,先手总操作不为0,后手总操作为0,最终,必败态(全部取完全0)一定会被后手先遇到,则先手胜。反之后手胜。

分析猛如虎,代码很简单。只需要把每个数读进来,异或一遍,看是不是0就行。

#include 
#include 

using namespace std;

int main ()
{
    int n;
    cin>>n;
    int res = 0;
    while (n -- )
    {
        int x;
        cin>>x;
        res ^= x;
    }
    if(res) puts("Yes");
    else puts("No");
    
    return 0;
}

你可能感兴趣的:(数论,力扣,博弈论,c++,算法)