题目描述:
有三堆石子,两个人轮流从其中一堆取1到任意颗石子,并约定取走所有三堆中最后一颗石子的人胜利。
现给定石子数量,问先手有没有必胜策略?
输入:
一行,三个正整数a,b,c表示石子数量,用空格隔开。
输入:
若先手必胜,输出2个整数x,y,表示先手第一步从第x堆石子取y颗,如果有多种方案致胜,输出所有方案,每行一个,按照取的石子的编号从小到大排序。
否则输出一行no。
数据范围:
分数 数据范围
10 max(a,b,c)<=10
30 max(a,b,c)<=50
30 max(a,b)<=50,c<=10000
20 max(a,b,c)<=10000
10 max(a,b,c)<2147483648
时间限制:1s
样例数据:
输入 输出
2 3 2 1 1
2 3
3 1
1 2 3 no
3 5 10 3 4
6 10 12 no
114514 1919893 1897671 no
样例解释:
第1组数据,先手可以取走3颗石子一堆的所有石子。
题解:本题目是个典型的Nim游戏。用到一个位运算:异或”^”。
首先一旦从xor为零的状态时取走至少一颗石子,xor就会变得不等于0,再后手取一个相同的数量(为啥见coin game题解),这时xor的值又变成0了!
所以必败态一定只能转到必胜态[惊不惊喜,意不意外]所以a1 xor a2 xor a3 xor a4 …… xor an的值如果等于零,则先手必败,因为最后一个石子是后手拿走的。
如果其值不等于0.则是必胜!好了,现在yes 和 no的问题解决了,再来看yes时的输出方案,如果a>(b^c),a只有在与b xor c相等时,才会a xor b xor c = 0 所以在第一堆当中取走a-(b^c),这时a=a-(a-(b^c))可以得出 a=b^c。因为第一次取完后,xor的值就等于0了。此时后手就成了“先手”,而xor等于0时“先手”必输,所以后手必输,不就是先手必胜吗!b和c的做法与a相同。得证!
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int a,b,c; int main() { freopen("tristone.in","r",stdin); freopen("tristone.out","w",stdout); cin>>a>>b>>c; if((a^b^c)==0) cout<<"no"; else { if(a>(b^c)) cout<<"1 "<<a-(b^c)<<endl; if(b>(a^c)) cout<<"2 "<<b-(a^c)<<endl; if(c>(a^b)) cout<<"3 "<<c-(a^b)<<endl; } return 0; }