C++-POJ2975-Nim
2024-10-08 10:48:58
题目把Nim游戏为什么可以取异或和讲解得十分清楚,建议多读几次,理解一下
再一个,可以把每次异或视为一次取数,因此(k[i]^sg)<k[i]即为一种可行操作
/*
Nim is a 2-player game featuring several piles of stones.
Players alternate turns, and on his/her turn, a player’s
move consists of removing one or more stones from any
single pile. Play ends when all the stones have been
removed, at which point the last player to have moved is
declared the winner. Given a position in Nim, your task
is to determine how many winning moves there are in that
position. A position in Nim is called “losing” if the first player
to move from that position would lose if both sides played
perfectly. A “winning move,” then, is a move that leaves
the game in a losing position. There is a famous theorem
that classifies all losing positions. Suppose a Nim position
contains n piles having k1, k2, …, kn stones respectively;
in such a position, there are k1 + k2 + … + kn possible
moves. We write each ki in binary (base 2). Then, the Nim
position is losing if and only if, among all the ki’s,
there are an even number of 1’s in each digit position.
In other words, the Nim position is losing if and only if
the xor of the ki’s is 0. Consider the position with three piles given by k1 = 7, k2
= 11, and k3 = 13. In binary, these values are as follows: 111
1011
1101 There are an odd number of 1’s among the rightmost digits,
so this position is not losing. However, suppose k3 were
changed to be 12. Then, there would be exactly two 1’s in
each digit position, and thus, the Nim position would become
losing. Since a winning move is any move that leaves the
game in a losing position, it follows that removing one
stone from the third pile is a winning move when k1 = 7, k2
= 11, and k3 = 13. In fact, there are exactly three winning
moves from this position: namely removing one stone from any
of the three piles.
*/
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n,k[];
int main(){
while(scanf("%d",&n)){
if(n==)break;
int sg=,ans=;
for(int i=;i<=n;i++)scanf("%d",&k[i]),sg^=k[i];
for(int i=;i<=n;i++)if((k[i]^sg)<k[i])ans++;
printf("%d\n",ans);
}
return ;
}
最新文章
- sql语句,order by
- MVC 缓存
- C# 非托管内存使用时的注意事项
- jqgrid在colModel中多次调用同一个字段值
- jquery 学习
- STM32 ucosii 串口接收数据 遇到的问题及解决思路
- 这些小众软件让你的效率提升N倍!(必备,收藏)
- module_init宏解析
- 实现Runnable接口和扩展Thread使用场景
- DeepLearning.ai学习笔记(四)卷积神经网络 -- week1 卷积神经网络基础知识介绍
- 华科机考:N阶楼梯上楼
- Git之(六)标签管理
- 修改MAC地址的方法 破解MAC地址绑定(抄)
- C# Selenium学习
- 在Windows Server 2008 R2 Server中,上传视频遇到的问题(二)
- 使用keepalived实现双机热备
- AppScan--图解Web扫描工具IBM Security App Scan Standard
- Hadoop hostname: Unknown host
- 神经网络中的池化层(pooling)
- 【HNOI2015】落忆枫音