nim博弈 hdu2176 取(m堆)石子游戏
2015-12-10 18:27
337 查看
传送门:点击打开链接
题意:m堆石子轮流取,每次只能对一堆操作,每次必须要取,取的石子数量没有上限。第一个取完的胜利。问最后是否能赢,第一步要怎样才能赢、
思路:nim博弈,根据SG函数定理,如果是独立游戏,那么应该是所有独立游戏的SG函数的异或值。
很容易可以发现,对于每一堆石子的SG函数都等于石子的个数,所以就相当于求所有石子个数的异或值看是否等于0,如果等于,说明先手必输,否则说明先手必赢
题意:m堆石子轮流取,每次只能对一堆操作,每次必须要取,取的石子数量没有上限。第一个取完的胜利。问最后是否能赢,第一步要怎样才能赢、
思路:nim博弈,根据SG函数定理,如果是独立游戏,那么应该是所有独立游戏的SG函数的异或值。
很容易可以发现,对于每一堆石子的SG函数都等于石子的个数,所以就相当于求所有石子个数的异或值看是否等于0,如果等于,说明先手必输,否则说明先手必赢
#include<map> #include<set> #include<cmath> #include<ctime> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<string> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #define fuck(x) cout<<"["<<x<<"]" #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w+",stdout) using namespace std; typedef long long LL; typedef pair<int, int>PII; const int MX = 5e5 + 5; int A[MX], rear; PII ans[MX]; int main() { int m; //FIN; while(~scanf("%d", &m), m) { int sum = 0; rear = 0; for(int i = 1; i <= m; i++) { scanf("%d", &A[i]); sum ^= A[i]; } for(int i = 1; i <= m; i++) { if((sum ^ A[i]) < A[i]) ans[++rear] = PII(A[i], sum ^ A[i]); } if(!rear) printf("No\n"); else { printf("Yes\n"); for(int i = 1; i <= rear; i++) { printf("%d %d\n", ans[i].first, ans[i].second); } } } return 0; }
相关文章推荐
- ANT(重要思想!)
- 在centos7中安装mysql(mariadb)
- Java Sax解析xml
- 【Html】垂直居中-父元素高度确定的多行文本(方法一)
- Apache Spark 学习笔记(1)
- 《HTTP权威指南》– 16.重定向与负载均衡
- dubbo集群容错机制
- 七种网卡绑定模式详解
- 【网络流】:poj1087,A Plug for UNIX
- UIImageView添加点击事件
- WCDMA常用概念
- Mybatis工作原理
- 第四篇 虚拟机类加载机制
- dubbo超时
- 使用swift集成移动广告聚合平台
- 手机淘宝 521 性能优化项目揭秘
- StringTokenizer用法
- BZOJ1191(二分图匹配)
- HOJ2275 Number sequence
- LVS 服务器集群三种实现模式配置