取(m堆)石子游戏 【传送门】
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5138 Accepted Submission(s): 3094
Problem Description
m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子.例如5堆 5,7,8,9,10先取者胜,先取者第1次取时可以从有8个的那一堆取走7个剩下1个,也可以从有9个的中那一堆取走9个剩下0个,也可以从有10个的中那一堆取走7个剩下3个.
Input
输入有多组.每组第1行是m,m<=200000. 后面m个非零正整数.m=0退出.
Output
先取者负输出No.先取者胜输出Yes,然后输出先取者第1次取子的所有方法.如果从有a个石子的堆中取若干个后剩下b个后会胜就输出a b.参看Sample Output.
Sample Input
2
45 45
3
3 6 9
5
5 7 8 9 10
0
Sample Output
No
Yes
9 5
Yes
8 1
9 0
10 3
Author
Zhousc
Source
尼姆博弈,详解专题链接:https://blog.csdn.net/lesileqin/article/details/98525887
AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#include<algorithm>
#include<queue>
#include<stack>
using namespace std;
#define INF 999999
#define MOD 2009
#define MAXN 200000+5
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long ll;
int main(){
ios::sync_with_stdio(false);
int m;
while(cin >> m && m){
int res=0;
int n[MAXN];
for(int i=0;i<m;i++){
cin >> n[i];
res^=n[i];
}
if(res==0)
cout << "No\n";
else{
cout << "Yes\n";
int sum=0;
int tmp;
for(int i=0;i<m;i++){
tmp=res^n[i];
if(tmp<n[i])
cout << n[i] << " " << tmp << endl;
}
}
}
return 0;
}
本文探讨了m堆石子游戏中两人轮流取石子的策略,解析了如何判断先手胜负并提供具体取石策略。通过异或运算计算格雷码,当结果为0时,先手必败;否则,先手有胜机。文章提供了AC代码实现。
329

被折叠的 条评论
为什么被折叠?



